@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.
- package/dist/package.json +16 -10
- package/dist/src/commands/extensions/disable.d.ts +1 -1
- package/dist/src/commands/extensions/disable.js +15 -7
- package/dist/src/commands/extensions/disable.js.map +1 -1
- package/dist/src/commands/extensions/enable.d.ts +1 -1
- package/dist/src/commands/extensions/enable.js +15 -7
- package/dist/src/commands/extensions/enable.js.map +1 -1
- package/dist/src/commands/extensions/install.js +14 -3
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/install.test.js +39 -19
- package/dist/src/commands/extensions/install.test.js.map +1 -1
- package/dist/src/commands/extensions/link.js +14 -3
- package/dist/src/commands/extensions/link.js.map +1 -1
- package/dist/src/commands/extensions/list.js +13 -4
- package/dist/src/commands/extensions/list.js.map +1 -1
- package/dist/src/commands/extensions/uninstall.js +13 -2
- package/dist/src/commands/extensions/uninstall.js.map +1 -1
- package/dist/src/commands/extensions/update.js +18 -13
- package/dist/src/commands/extensions/update.js.map +1 -1
- package/dist/src/commands/extensions/validate.d.ts +12 -0
- package/dist/src/commands/extensions/validate.js +83 -0
- package/dist/src/commands/extensions/validate.js.map +1 -0
- package/dist/src/commands/extensions/validate.test.js +93 -0
- package/dist/src/commands/extensions/validate.test.js.map +1 -0
- package/dist/src/commands/extensions.js +3 -0
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/mcp/add.test.js +3 -0
- package/dist/src/commands/mcp/add.test.js.map +1 -1
- package/dist/src/commands/mcp/list.js +10 -3
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp/list.test.js +37 -27
- package/dist/src/commands/mcp/list.test.js.map +1 -1
- package/dist/src/config/auth.js +0 -5
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/config.d.ts +6 -3
- package/dist/src/config/config.js +65 -80
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +235 -212
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/extension-manager.d.ts +63 -0
- package/dist/src/config/extension-manager.js +450 -0
- package/dist/src/config/extension-manager.js.map +1 -0
- package/dist/src/config/extension.d.ts +4 -51
- package/dist/src/config/extension.js +1 -535
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/extension.test.js +525 -201
- package/dist/src/config/extension.test.js.map +1 -1
- package/dist/src/config/extensions/consent.d.ts +38 -0
- package/dist/src/config/extensions/consent.js +123 -0
- package/dist/src/config/extensions/consent.js.map +1 -0
- package/dist/src/config/extensions/extensionEnablement.d.ts +1 -1
- package/dist/src/config/extensions/extensionEnablement.js +4 -3
- package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
- package/dist/src/config/extensions/extensionEnablement.test.js +10 -10
- package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
- package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
- package/dist/src/config/extensions/extensionSettings.js +113 -0
- package/dist/src/config/extensions/extensionSettings.js.map +1 -0
- package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
- package/dist/src/config/extensions/extensionSettings.test.js +254 -0
- package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
- package/dist/src/config/extensions/github.d.ts +2 -2
- package/dist/src/config/extensions/github.js +5 -10
- package/dist/src/config/extensions/github.js.map +1 -1
- package/dist/src/config/extensions/github.test.js +153 -167
- package/dist/src/config/extensions/github.test.js.map +1 -1
- package/dist/src/config/extensions/github_fetch.d.ts +1 -1
- package/dist/src/config/extensions/github_fetch.js +13 -1
- package/dist/src/config/extensions/github_fetch.js.map +1 -1
- package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
- package/dist/src/config/extensions/github_fetch.test.js +169 -0
- package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
- package/dist/src/config/extensions/storage.d.ts +14 -0
- package/dist/src/config/extensions/storage.js +32 -0
- package/dist/src/config/extensions/storage.js.map +1 -0
- package/dist/src/config/extensions/update.d.ts +4 -4
- package/dist/src/config/extensions/update.js +39 -39
- package/dist/src/config/extensions/update.js.map +1 -1
- package/dist/src/config/extensions/update.test.js +72 -74
- package/dist/src/config/extensions/update.test.js.map +1 -1
- package/dist/src/config/extensions/variableSchema.d.ts +0 -6
- package/dist/src/config/extensions/variableSchema.js.map +1 -1
- package/dist/src/config/extensions/variables.d.ts +4 -0
- package/dist/src/config/extensions/variables.js +6 -0
- package/dist/src/config/extensions/variables.js.map +1 -1
- package/dist/src/config/keyBindings.d.ts +3 -0
- package/dist/src/config/keyBindings.js +30 -8
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/keyBindings.test.js +17 -0
- package/dist/src/config/keyBindings.test.js.map +1 -1
- package/dist/src/config/policies/read-only.toml +56 -0
- package/dist/src/config/policies/write.toml +63 -0
- package/dist/src/config/policies/yolo.toml +31 -0
- package/dist/src/config/policy-engine.integration.test.js +41 -38
- package/dist/src/config/policy-engine.integration.test.js.map +1 -1
- package/dist/src/config/policy.d.ts +2 -2
- package/dist/src/config/policy.js +10 -148
- package/dist/src/config/policy.js.map +1 -1
- package/dist/src/config/sandboxConfig.d.ts +1 -1
- package/dist/src/config/sandboxConfig.js +6 -3
- package/dist/src/config/sandboxConfig.js.map +1 -1
- package/dist/src/config/settings.d.ts +2 -1
- package/dist/src/config/settings.js +58 -18
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settings.test.js +128 -69
- package/dist/src/config/settings.test.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +170 -28
- package/dist/src/config/settingsSchema.js +418 -27
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.js +42 -1
- package/dist/src/config/settingsSchema.test.js.map +1 -1
- package/dist/src/config/trustedFolders.d.ts +1 -1
- package/dist/src/config/trustedFolders.js +4 -2
- package/dist/src/config/trustedFolders.js.map +1 -1
- package/dist/src/core/initializer.js +2 -1
- package/dist/src/core/initializer.js.map +1 -1
- package/dist/src/gemini.d.ts +1 -1
- package/dist/src/gemini.js +46 -16
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +88 -30
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/nonInteractiveCli.d.ts +9 -1
- package/dist/src/nonInteractiveCli.js +114 -7
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.js +355 -112
- package/dist/src/nonInteractiveCli.test.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.js +4 -0
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.test.js +22 -0
- package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
- package/dist/src/services/FeedbackService.js +2 -2
- package/dist/src/services/FeedbackService.js.map +1 -1
- package/dist/src/services/McpPromptLoader.js +2 -2
- package/dist/src/services/McpPromptLoader.js.map +1 -1
- package/dist/src/services/McpPromptLoader.test.js +4 -2
- package/dist/src/services/McpPromptLoader.test.js.map +1 -1
- package/dist/src/test-utils/async.d.ts +9 -0
- package/dist/src/test-utils/async.js +29 -0
- package/dist/src/test-utils/async.js.map +1 -0
- package/dist/src/test-utils/createExtension.d.ts +3 -1
- package/dist/src/test-utils/createExtension.js +3 -3
- package/dist/src/test-utils/createExtension.js.map +1 -1
- package/dist/src/test-utils/render.d.ts +16 -2
- package/dist/src/test-utils/render.js +66 -4
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/test-utils/render.test.d.ts +6 -0
- package/dist/src/test-utils/render.test.js +79 -0
- package/dist/src/test-utils/render.test.js.map +1 -0
- package/dist/src/ui/App.test.js +1 -1
- package/dist/src/ui/App.test.js.map +1 -1
- package/dist/src/ui/AppContainer.js +181 -65
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +505 -147
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/IdeIntegrationNudge.js +1 -1
- package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
- package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
- package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
- package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
- package/dist/src/ui/auth/AuthDialog.js +7 -3
- package/dist/src/ui/auth/AuthDialog.js.map +1 -1
- package/dist/src/ui/auth/useAuth.d.ts +2 -0
- package/dist/src/ui/auth/useAuth.js +31 -2
- package/dist/src/ui/auth/useAuth.js.map +1 -1
- package/dist/src/ui/colors.js +3 -0
- package/dist/src/ui/colors.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.js +1 -1
- package/dist/src/ui/commands/directoryCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.js +64 -11
- package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.test.js +72 -1
- package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.js +14 -14
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.test.js +4 -0
- package/dist/src/ui/commands/mcpCommand.test.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.js +1 -1
- package/dist/src/ui/commands/memoryCommand.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.test.js +3 -1
- package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
- package/dist/src/ui/commands/policiesCommand.d.ts +7 -0
- package/dist/src/ui/commands/policiesCommand.js +59 -0
- package/dist/src/ui/commands/policiesCommand.js.map +1 -0
- package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/policiesCommand.test.js +83 -0
- package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
- package/dist/src/ui/components/AnsiOutput.test.js +1 -1
- package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
- package/dist/src/ui/components/AsciiArt.d.ts +3 -3
- package/dist/src/ui/components/AsciiArt.js +3 -3
- package/dist/src/ui/components/Composer.js +1 -1
- package/dist/src/ui/components/Composer.js.map +1 -1
- package/dist/src/ui/components/Composer.test.js +5 -2
- package/dist/src/ui/components/Composer.test.js.map +1 -1
- package/dist/src/ui/components/ConfigInitDisplay.js +4 -6
- package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
- package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
- package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
- package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
- package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
- package/dist/src/ui/components/ContextSummaryDisplay.test.js +11 -6
- package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -1
- package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
- package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +4 -0
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +2 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.js +4 -3
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/Footer.test.js +83 -0
- package/dist/src/ui/components/Footer.test.js.map +1 -1
- package/dist/src/ui/components/Header.test.js +13 -5
- package/dist/src/ui/components/Header.test.js.map +1 -1
- package/dist/src/ui/components/Help.test.js +5 -4
- package/dist/src/ui/components/Help.test.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +27 -8
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.js +776 -727
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.js +2 -2
- package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.test.js +28 -15
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.js +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.js.map +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.test.js +2 -2
- package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +1 -1
- package/dist/src/ui/components/MainContent.js +15 -4
- package/dist/src/ui/components/MainContent.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.js +1 -1
- package/dist/src/ui/components/ModelDialog.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.test.js +23 -13
- package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.js +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/Notifications.js +38 -5
- package/dist/src/ui/components/Notifications.js.map +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +2 -2
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/PrepareLabel.test.js +14 -8
- package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
- package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
- package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
- package/dist/src/ui/components/QueuedMessageDisplay.test.js +11 -6
- package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.test.js +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.js +32 -25
- package/dist/src/ui/components/SettingsDialog.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +428 -532
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.test.js +2 -2
- package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
- package/dist/src/ui/components/ThemeDialog.test.js +2 -2
- package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.js +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
- package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
- package/dist/src/ui/components/messages/InfoMessage.js +1 -1
- package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.js +27 -5
- package/dist/src/ui/components/messages/Todo.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.test.js +20 -8
- package/dist/src/ui/components/messages/Todo.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/WarningMessage.js +2 -2
- package/dist/src/ui/components/messages/WarningMessage.js.map +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
- package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
- package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
- package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
- package/dist/src/ui/components/shared/TextInput.js +38 -0
- package/dist/src/ui/components/shared/TextInput.js.map +1 -0
- package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
- package/dist/src/ui/components/shared/TextInput.test.js +242 -0
- package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
- package/dist/src/ui/components/shared/text-buffer.d.ts +9 -2
- package/dist/src/ui/components/shared/text-buffer.js +51 -13
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.test.js +385 -202
- package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
- package/dist/src/ui/components/views/ChatList.test.js +7 -4
- package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
- package/dist/src/ui/components/views/ExtensionsList.js +9 -11
- package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.test.js +43 -22
- package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
- package/dist/src/ui/components/views/McpStatus.test.js +23 -12
- package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.d.ts +3 -2
- package/dist/src/ui/contexts/KeypressContext.js +610 -540
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +438 -718
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/MouseContext.d.ts +21 -0
- package/dist/src/ui/contexts/MouseContext.js +89 -0
- package/dist/src/ui/contexts/MouseContext.js.map +1 -0
- package/dist/src/ui/contexts/MouseContext.test.d.ts +6 -0
- package/dist/src/ui/contexts/MouseContext.test.js +164 -0
- package/dist/src/ui/contexts/MouseContext.test.js.map +1 -0
- package/dist/src/ui/contexts/SessionContext.test.js +35 -17
- package/dist/src/ui/contexts/SessionContext.test.js.map +1 -1
- package/dist/src/ui/contexts/UIActionsContext.d.ts +2 -0
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/contexts/UIStateContext.d.ts +2 -0
- package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.js +31 -9
- package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
- package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.js +64 -35
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.test.js +193 -165
- package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/useAtCompletion.test.js +16 -5
- package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +32 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.js +66 -64
- package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useConsoleMessages.test.js +26 -9
- package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
- package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
- package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -5
- package/dist/src/ui/hooks/useExtensionUpdates.js +18 -13
- package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.test.js +49 -44
- package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
- package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
- package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
- package/dist/src/ui/hooks/useFocus.test.js +25 -9
- package/dist/src/ui/hooks/useFocus.test.js.map +1 -1
- package/dist/src/ui/hooks/useFolderTrust.test.js +46 -22
- package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.js +56 -19
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.js +260 -411
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.js +4 -0
- package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.test.js +46 -34
- package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
- package/dist/src/ui/hooks/useIdeTrustListener.test.js +40 -9
- package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
- package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
- package/dist/src/ui/hooks/useKeypress.test.js +103 -114
- package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +24 -6
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
- package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
- package/dist/src/ui/hooks/useMessageQueue.test.js +62 -45
- package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
- package/dist/src/ui/hooks/useModelCommand.test.js +21 -11
- package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
- package/dist/src/ui/hooks/useMouse.d.ts +17 -0
- package/dist/src/ui/hooks/useMouse.js +27 -0
- package/dist/src/ui/hooks/useMouse.js.map +1 -0
- package/dist/src/ui/hooks/useMouse.test.d.ts +6 -0
- package/dist/src/ui/hooks/useMouse.test.js +57 -0
- package/dist/src/ui/hooks/useMouse.test.js.map +1 -0
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.test.js +109 -106
- package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -6
- package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
- package/dist/src/ui/hooks/usePromptCompletion.js +2 -2
- package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
- package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js +55 -48
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
- package/dist/src/ui/hooks/useReactToolScheduler.js +59 -34
- package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.js +5 -4
- package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.test.js +272 -183
- package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
- package/dist/src/ui/hooks/useShellHistory.test.js +52 -20
- package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.js +18 -7
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +275 -137
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useTimer.test.js +43 -14
- package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +226 -242
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/hooks/vim.test.js +235 -355
- package/dist/src/ui/hooks/vim.test.js.map +1 -1
- package/dist/src/ui/keyMatchers.test.js +30 -3
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/state/extensions.d.ts +1 -0
- package/dist/src/ui/state/extensions.js +1 -0
- package/dist/src/ui/state/extensions.js.map +1 -1
- package/dist/src/ui/themes/ansi-light.js +1 -0
- package/dist/src/ui/themes/ansi-light.js.map +1 -1
- package/dist/src/ui/themes/ansi.js +1 -0
- package/dist/src/ui/themes/ansi.js.map +1 -1
- package/dist/src/ui/themes/atom-one-dark.js +2 -0
- package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
- package/dist/src/ui/themes/ayu-light.js +2 -0
- package/dist/src/ui/themes/ayu-light.js.map +1 -1
- package/dist/src/ui/themes/ayu.js +2 -0
- package/dist/src/ui/themes/ayu.js.map +1 -1
- package/dist/src/ui/themes/color-utils.d.ts +1 -0
- package/dist/src/ui/themes/color-utils.js +6 -0
- package/dist/src/ui/themes/color-utils.js.map +1 -1
- package/dist/src/ui/themes/color-utils.test.js +13 -1
- package/dist/src/ui/themes/color-utils.test.js.map +1 -1
- package/dist/src/ui/themes/dracula.js +2 -0
- package/dist/src/ui/themes/dracula.js.map +1 -1
- package/dist/src/ui/themes/github-dark.js +2 -0
- package/dist/src/ui/themes/github-dark.js.map +1 -1
- package/dist/src/ui/themes/github-light.js +2 -0
- package/dist/src/ui/themes/github-light.js.map +1 -1
- package/dist/src/ui/themes/googlecode.js +2 -0
- package/dist/src/ui/themes/googlecode.js.map +1 -1
- package/dist/src/ui/themes/no-color.js +3 -0
- package/dist/src/ui/themes/no-color.js.map +1 -1
- package/dist/src/ui/themes/semantic-tokens.d.ts +2 -0
- package/dist/src/ui/themes/semantic-tokens.js +6 -0
- package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
- package/dist/src/ui/themes/shades-of-purple.js +2 -0
- package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
- package/dist/src/ui/themes/theme.d.ts +3 -0
- package/dist/src/ui/themes/theme.js +14 -3
- package/dist/src/ui/themes/theme.js.map +1 -1
- package/dist/src/ui/themes/theme.test.js +67 -1
- package/dist/src/ui/themes/theme.test.js.map +1 -1
- package/dist/src/ui/themes/xcode.js +2 -0
- package/dist/src/ui/themes/xcode.js.map +1 -1
- package/dist/src/ui/types.d.ts +3 -1
- package/dist/src/ui/types.js +2 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/CodeColorizer.js +2 -1
- package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
- package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
- package/dist/src/ui/utils/InlineMarkdownRenderer.js +11 -10
- package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
- package/dist/src/ui/utils/MarkdownDisplay.js +11 -9
- package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
- package/dist/src/ui/utils/clipboardUtils.js +2 -2
- package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
- package/dist/src/ui/utils/input.d.ts +17 -0
- package/dist/src/ui/utils/input.js +51 -0
- package/dist/src/ui/utils/input.js.map +1 -0
- package/dist/src/ui/utils/input.test.d.ts +6 -0
- package/dist/src/ui/utils/input.test.js +44 -0
- package/dist/src/ui/utils/input.test.js.map +1 -0
- package/dist/src/ui/utils/kittyProtocolDetector.js +13 -4
- package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
- package/dist/src/ui/utils/mouse.d.ts +31 -0
- package/dist/src/ui/utils/mouse.js +164 -0
- package/dist/src/ui/utils/mouse.js.map +1 -0
- package/dist/src/ui/utils/mouse.test.d.ts +6 -0
- package/dist/src/ui/utils/mouse.test.js +131 -0
- package/dist/src/ui/utils/mouse.test.js.map +1 -0
- package/dist/src/ui/utils/textOutput.d.ts +25 -0
- package/dist/src/ui/utils/textOutput.js +49 -0
- package/dist/src/ui/utils/textOutput.js.map +1 -0
- package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
- package/dist/src/ui/utils/textOutput.test.js +79 -0
- package/dist/src/ui/utils/textOutput.test.js.map +1 -0
- package/dist/src/ui/utils/updateCheck.d.ts +7 -1
- package/dist/src/ui/utils/updateCheck.js +33 -29
- package/dist/src/ui/utils/updateCheck.js.map +1 -1
- package/dist/src/ui/utils/updateCheck.test.js +24 -50
- package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
- package/dist/src/utils/commentJson.js +2 -2
- package/dist/src/utils/commentJson.js.map +1 -1
- package/dist/src/utils/commentJson.test.js +7 -6
- package/dist/src/utils/commentJson.test.js.map +1 -1
- package/dist/src/utils/envVarResolver.d.ts +2 -2
- package/dist/src/utils/envVarResolver.js +10 -7
- package/dist/src/utils/envVarResolver.js.map +1 -1
- package/dist/src/utils/events.d.ts +11 -2
- package/dist/src/utils/events.js +1 -0
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/handleAutoUpdate.js +9 -3
- package/dist/src/utils/handleAutoUpdate.js.map +1 -1
- package/dist/src/utils/sandbox.js +16 -18
- package/dist/src/utils/sandbox.js.map +1 -1
- package/dist/src/utils/version.js +6 -2
- package/dist/src/utils/version.js.map +1 -1
- package/dist/src/zed-integration/acp.js +2 -1
- package/dist/src/zed-integration/acp.js.map +1 -1
- package/dist/src/zed-integration/schema.d.ts +4 -4
- package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
- package/dist/src/zed-integration/zedIntegration.js +12 -19
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -14
- package/dist/src/config/policy.test.js +0 -360
- package/dist/src/config/policy.test.js.map +0 -1
- package/dist/src/utils/package.d.ts +0 -12
- package/dist/src/utils/package.js +0 -24
- package/dist/src/utils/package.js.map +0 -1
- /package/dist/src/{config/policy.test.d.ts → commands/extensions/validate.test.d.ts} +0 -0
|
@@ -5,13 +5,28 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
5
5
|
* SPDX-License-Identifier: Apache-2.0
|
|
6
6
|
*/
|
|
7
7
|
import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest';
|
|
8
|
-
import { render
|
|
8
|
+
import { render } from '../test-utils/render.js';
|
|
9
|
+
import { cleanup } from 'ink-testing-library';
|
|
10
|
+
import { act, useContext } from 'react';
|
|
9
11
|
import { AppContainer } from './AppContainer.js';
|
|
10
|
-
import { makeFakeConfig } from '@google/gemini-cli-core';
|
|
12
|
+
import { makeFakeConfig, CoreEvent, } from '@google/gemini-cli-core';
|
|
13
|
+
// Mock coreEvents
|
|
14
|
+
const mockCoreEvents = vi.hoisted(() => ({
|
|
15
|
+
on: vi.fn(),
|
|
16
|
+
off: vi.fn(),
|
|
17
|
+
drainFeedbackBacklog: vi.fn(),
|
|
18
|
+
emit: vi.fn(),
|
|
19
|
+
}));
|
|
20
|
+
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
|
21
|
+
const actual = await importOriginal();
|
|
22
|
+
return {
|
|
23
|
+
...actual,
|
|
24
|
+
coreEvents: mockCoreEvents,
|
|
25
|
+
};
|
|
26
|
+
});
|
|
11
27
|
import { useQuotaAndFallback } from './hooks/useQuotaAndFallback.js';
|
|
12
28
|
import { UIStateContext } from './contexts/UIStateContext.js';
|
|
13
29
|
import { UIActionsContext, } from './contexts/UIActionsContext.js';
|
|
14
|
-
import { useContext } from 'react';
|
|
15
30
|
// Mock useStdout to capture terminal title writes
|
|
16
31
|
let mockStdout;
|
|
17
32
|
vi.mock('ink', async (importOriginal) => {
|
|
@@ -66,6 +81,10 @@ vi.mock('../utils/events.js');
|
|
|
66
81
|
vi.mock('../utils/handleAutoUpdate.js');
|
|
67
82
|
vi.mock('./utils/ConsolePatcher.js');
|
|
68
83
|
vi.mock('../utils/cleanup.js');
|
|
84
|
+
vi.mock('./utils/mouse.js', () => ({
|
|
85
|
+
enableMouseEvents: vi.fn(),
|
|
86
|
+
disableMouseEvents: vi.fn(),
|
|
87
|
+
}));
|
|
69
88
|
import { useHistory } from './hooks/useHistoryManager.js';
|
|
70
89
|
import { useThemeCommand } from './hooks/useThemeCommand.js';
|
|
71
90
|
import { useAuthCommand } from './auth/useAuth.js';
|
|
@@ -86,13 +105,17 @@ import { useSessionStats } from './contexts/SessionContext.js';
|
|
|
86
105
|
import { useTextBuffer } from './components/shared/text-buffer.js';
|
|
87
106
|
import { useLogger } from './hooks/useLogger.js';
|
|
88
107
|
import { useLoadingIndicator } from './hooks/useLoadingIndicator.js';
|
|
108
|
+
import { useKeypress } from './hooks/useKeypress.js';
|
|
89
109
|
import { measureElement } from 'ink';
|
|
90
110
|
import { useTerminalSize } from './hooks/useTerminalSize.js';
|
|
91
111
|
import { ShellExecutionService } from '@google/gemini-cli-core';
|
|
112
|
+
import {} from '../config/extension-manager.js';
|
|
113
|
+
import { enableMouseEvents, disableMouseEvents } from './utils/mouse.js';
|
|
92
114
|
describe('AppContainer State Management', () => {
|
|
93
115
|
let mockConfig;
|
|
94
116
|
let mockSettings;
|
|
95
117
|
let mockInitResult;
|
|
118
|
+
let mockExtensionManager;
|
|
96
119
|
// Create typed mocks for all hooks
|
|
97
120
|
const mockedUseQuotaAndFallback = useQuotaAndFallback;
|
|
98
121
|
const mockedUseHistory = useHistory;
|
|
@@ -115,6 +138,7 @@ describe('AppContainer State Management', () => {
|
|
|
115
138
|
const mockedUseTextBuffer = useTextBuffer;
|
|
116
139
|
const mockedUseLogger = useLogger;
|
|
117
140
|
const mockedUseLoadingIndicator = useLoadingIndicator;
|
|
141
|
+
const mockedUseKeypress = useKeypress;
|
|
118
142
|
beforeEach(() => {
|
|
119
143
|
vi.clearAllMocks();
|
|
120
144
|
// Initialize mock stdout for terminal title tests
|
|
@@ -235,6 +259,13 @@ describe('AppContainer State Management', () => {
|
|
|
235
259
|
mockConfig = makeFakeConfig();
|
|
236
260
|
// Mock config's getTargetDir to return consistent workspace directory
|
|
237
261
|
vi.spyOn(mockConfig, 'getTargetDir').mockReturnValue('/test/workspace');
|
|
262
|
+
mockExtensionManager = vi.mockObject({
|
|
263
|
+
getExtensions: vi.fn().mockReturnValue([]),
|
|
264
|
+
setRequestConsent: vi.fn(),
|
|
265
|
+
setRequestSetting: vi.fn(),
|
|
266
|
+
start: vi.fn(),
|
|
267
|
+
});
|
|
268
|
+
vi.spyOn(mockConfig, 'getExtensionLoader').mockReturnValue(mockExtensionManager);
|
|
238
269
|
// Mock LoadedSettings
|
|
239
270
|
mockSettings = {
|
|
240
271
|
merged: {
|
|
@@ -261,27 +292,33 @@ describe('AppContainer State Management', () => {
|
|
|
261
292
|
cleanup();
|
|
262
293
|
});
|
|
263
294
|
describe('Basic Rendering', () => {
|
|
264
|
-
it('renders without crashing with minimal props', () => {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
295
|
+
it('renders without crashing with minimal props', async () => {
|
|
296
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
297
|
+
await act(async () => {
|
|
298
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
299
|
+
});
|
|
300
|
+
unmount();
|
|
268
301
|
});
|
|
269
|
-
it('renders with startup warnings', () => {
|
|
302
|
+
it('renders with startup warnings', async () => {
|
|
270
303
|
const startupWarnings = ['Warning 1', 'Warning 2'];
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
304
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, startupWarnings: startupWarnings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
305
|
+
await act(async () => {
|
|
306
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
307
|
+
});
|
|
308
|
+
unmount();
|
|
274
309
|
});
|
|
275
310
|
});
|
|
276
311
|
describe('State Initialization', () => {
|
|
277
|
-
it('initializes with theme error from initialization result', () => {
|
|
312
|
+
it('initializes with theme error from initialization result', async () => {
|
|
278
313
|
const initResultWithError = {
|
|
279
314
|
...mockInitResult,
|
|
280
315
|
themeError: 'Failed to load theme',
|
|
281
316
|
};
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
317
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: initResultWithError }));
|
|
318
|
+
await act(async () => {
|
|
319
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
320
|
+
});
|
|
321
|
+
unmount();
|
|
285
322
|
});
|
|
286
323
|
it('handles debug mode state', () => {
|
|
287
324
|
const debugConfig = makeFakeConfig();
|
|
@@ -292,29 +329,38 @@ describe('AppContainer State Management', () => {
|
|
|
292
329
|
});
|
|
293
330
|
});
|
|
294
331
|
describe('Context Providers', () => {
|
|
295
|
-
it('provides AppContext with correct values', () => {
|
|
332
|
+
it('provides AppContext with correct values', async () => {
|
|
296
333
|
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "2.0.0", initializationResult: mockInitResult }));
|
|
334
|
+
await act(async () => {
|
|
335
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
336
|
+
});
|
|
297
337
|
// Should render and unmount cleanly
|
|
298
338
|
expect(() => unmount()).not.toThrow();
|
|
299
339
|
});
|
|
300
|
-
it('provides UIStateContext with state management', () => {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
340
|
+
it('provides UIStateContext with state management', async () => {
|
|
341
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
342
|
+
await act(async () => {
|
|
343
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
344
|
+
});
|
|
345
|
+
unmount();
|
|
304
346
|
});
|
|
305
|
-
it('provides UIActionsContext with action handlers', () => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
347
|
+
it('provides UIActionsContext with action handlers', async () => {
|
|
348
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
349
|
+
await act(async () => {
|
|
350
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
351
|
+
});
|
|
352
|
+
unmount();
|
|
309
353
|
});
|
|
310
|
-
it('provides ConfigContext with config object', () => {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
354
|
+
it('provides ConfigContext with config object', async () => {
|
|
355
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
356
|
+
await act(async () => {
|
|
357
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
358
|
+
});
|
|
359
|
+
unmount();
|
|
314
360
|
});
|
|
315
361
|
});
|
|
316
362
|
describe('Settings Integration', () => {
|
|
317
|
-
it('handles settings with all display options disabled', () => {
|
|
363
|
+
it('handles settings with all display options disabled', async () => {
|
|
318
364
|
const settingsAllHidden = {
|
|
319
365
|
merged: {
|
|
320
366
|
hideBanner: true,
|
|
@@ -323,11 +369,13 @@ describe('AppContainer State Management', () => {
|
|
|
323
369
|
showMemoryUsage: false,
|
|
324
370
|
},
|
|
325
371
|
};
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
372
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: settingsAllHidden, version: "1.0.0", initializationResult: mockInitResult }));
|
|
373
|
+
await act(async () => {
|
|
374
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
375
|
+
});
|
|
376
|
+
unmount();
|
|
329
377
|
});
|
|
330
|
-
it('handles settings with memory usage enabled', () => {
|
|
378
|
+
it('handles settings with memory usage enabled', async () => {
|
|
331
379
|
const settingsWithMemory = {
|
|
332
380
|
merged: {
|
|
333
381
|
hideBanner: false,
|
|
@@ -336,36 +384,44 @@ describe('AppContainer State Management', () => {
|
|
|
336
384
|
showMemoryUsage: true,
|
|
337
385
|
},
|
|
338
386
|
};
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
387
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: settingsWithMemory, version: "1.0.0", initializationResult: mockInitResult }));
|
|
388
|
+
await act(async () => {
|
|
389
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
390
|
+
});
|
|
391
|
+
unmount();
|
|
342
392
|
});
|
|
343
393
|
});
|
|
344
394
|
describe('Version Handling', () => {
|
|
345
|
-
it.each(['1.0.0', '2.1.3-beta', '3.0.0-nightly'])('handles version format: %s', (version) => {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
395
|
+
it.each(['1.0.0', '2.1.3-beta', '3.0.0-nightly'])('handles version format: %s', async (version) => {
|
|
396
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: version, initializationResult: mockInitResult }));
|
|
397
|
+
await act(async () => {
|
|
398
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
399
|
+
});
|
|
400
|
+
unmount();
|
|
349
401
|
});
|
|
350
402
|
});
|
|
351
403
|
describe('Error Handling', () => {
|
|
352
|
-
it('handles config methods that might throw', () => {
|
|
404
|
+
it('handles config methods that might throw', async () => {
|
|
353
405
|
const errorConfig = makeFakeConfig();
|
|
354
406
|
vi.spyOn(errorConfig, 'getModel').mockImplementation(() => {
|
|
355
407
|
throw new Error('Config error');
|
|
356
408
|
});
|
|
357
409
|
// Should still render without crashing - errors should be handled internally
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
410
|
+
const { unmount } = render(_jsx(AppContainer, { config: errorConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
411
|
+
await act(async () => {
|
|
412
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
413
|
+
});
|
|
414
|
+
unmount();
|
|
361
415
|
});
|
|
362
|
-
it('handles undefined settings gracefully', () => {
|
|
416
|
+
it('handles undefined settings gracefully', async () => {
|
|
363
417
|
const undefinedSettings = {
|
|
364
418
|
merged: {},
|
|
365
419
|
};
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
420
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: undefinedSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
421
|
+
await act(async () => {
|
|
422
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
423
|
+
});
|
|
424
|
+
unmount();
|
|
369
425
|
});
|
|
370
426
|
});
|
|
371
427
|
describe('Provider Hierarchy', () => {
|
|
@@ -377,13 +433,17 @@ describe('AppContainer State Management', () => {
|
|
|
377
433
|
});
|
|
378
434
|
});
|
|
379
435
|
describe('Quota and Fallback Integration', () => {
|
|
380
|
-
it('passes a null proQuotaRequest to UIStateContext by default', () => {
|
|
436
|
+
it('passes a null proQuotaRequest to UIStateContext by default', async () => {
|
|
381
437
|
// The default mock from beforeEach already sets proQuotaRequest to null
|
|
382
|
-
render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
438
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
439
|
+
await act(async () => {
|
|
440
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
441
|
+
});
|
|
383
442
|
// Assert that the context value is as expected
|
|
384
443
|
expect(capturedUIState.proQuotaRequest).toBeNull();
|
|
444
|
+
unmount();
|
|
385
445
|
});
|
|
386
|
-
it('passes a valid proQuotaRequest to UIStateContext when provided by the hook', () => {
|
|
446
|
+
it('passes a valid proQuotaRequest to UIStateContext when provided by the hook', async () => {
|
|
387
447
|
// Arrange: Create a mock request object that a UI dialog would receive
|
|
388
448
|
const mockRequest = {
|
|
389
449
|
failedModel: 'gemini-pro',
|
|
@@ -395,11 +455,15 @@ describe('AppContainer State Management', () => {
|
|
|
395
455
|
handleProQuotaChoice: vi.fn(),
|
|
396
456
|
});
|
|
397
457
|
// Act: Render the container
|
|
398
|
-
render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
458
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
459
|
+
await act(async () => {
|
|
460
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
461
|
+
});
|
|
399
462
|
// Assert: The mock request is correctly passed through the context
|
|
400
463
|
expect(capturedUIState.proQuotaRequest).toEqual(mockRequest);
|
|
464
|
+
unmount();
|
|
401
465
|
});
|
|
402
|
-
it('passes the handleProQuotaChoice function to UIActionsContext', () => {
|
|
466
|
+
it('passes the handleProQuotaChoice function to UIActionsContext', async () => {
|
|
403
467
|
// Arrange: Create a mock handler function
|
|
404
468
|
const mockHandler = vi.fn();
|
|
405
469
|
mockedUseQuotaAndFallback.mockReturnValue({
|
|
@@ -407,12 +471,18 @@ describe('AppContainer State Management', () => {
|
|
|
407
471
|
handleProQuotaChoice: mockHandler,
|
|
408
472
|
});
|
|
409
473
|
// Act: Render the container
|
|
410
|
-
render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
474
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
475
|
+
await act(async () => {
|
|
476
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
477
|
+
});
|
|
411
478
|
// Assert: The action in the context is the mock handler we provided
|
|
412
479
|
expect(capturedUIActions.handleProQuotaChoice).toBe(mockHandler);
|
|
413
480
|
// You can even verify that the plumbed function is callable
|
|
414
|
-
|
|
481
|
+
act(() => {
|
|
482
|
+
capturedUIActions.handleProQuotaChoice('auth');
|
|
483
|
+
});
|
|
415
484
|
expect(mockHandler).toHaveBeenCalledWith('auth');
|
|
485
|
+
unmount();
|
|
416
486
|
});
|
|
417
487
|
});
|
|
418
488
|
describe('Terminal Title Update Feature', () => {
|
|
@@ -661,37 +731,59 @@ describe('AppContainer State Management', () => {
|
|
|
661
731
|
vi.useRealTimers();
|
|
662
732
|
});
|
|
663
733
|
it('should set and clear the queue error message after a timeout', async () => {
|
|
664
|
-
const { rerender } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
734
|
+
const { rerender, unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
735
|
+
await act(async () => {
|
|
736
|
+
vi.advanceTimersByTime(0);
|
|
737
|
+
});
|
|
665
738
|
expect(capturedUIState.queueErrorMessage).toBeNull();
|
|
666
|
-
|
|
739
|
+
act(() => {
|
|
740
|
+
capturedUIActions.setQueueErrorMessage('Test error');
|
|
741
|
+
});
|
|
667
742
|
rerender(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
668
743
|
expect(capturedUIState.queueErrorMessage).toBe('Test error');
|
|
669
|
-
|
|
744
|
+
act(() => {
|
|
745
|
+
vi.advanceTimersByTime(3000);
|
|
746
|
+
});
|
|
670
747
|
rerender(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
671
748
|
expect(capturedUIState.queueErrorMessage).toBeNull();
|
|
749
|
+
unmount();
|
|
672
750
|
});
|
|
673
751
|
it('should reset the timer if a new error message is set', async () => {
|
|
674
|
-
const { rerender } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
675
|
-
|
|
752
|
+
const { rerender, unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
753
|
+
await act(async () => {
|
|
754
|
+
vi.advanceTimersByTime(0);
|
|
755
|
+
});
|
|
756
|
+
act(() => {
|
|
757
|
+
capturedUIActions.setQueueErrorMessage('First error');
|
|
758
|
+
});
|
|
676
759
|
rerender(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
677
760
|
expect(capturedUIState.queueErrorMessage).toBe('First error');
|
|
678
|
-
|
|
679
|
-
|
|
761
|
+
act(() => {
|
|
762
|
+
vi.advanceTimersByTime(1500);
|
|
763
|
+
});
|
|
764
|
+
act(() => {
|
|
765
|
+
capturedUIActions.setQueueErrorMessage('Second error');
|
|
766
|
+
});
|
|
680
767
|
rerender(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
681
768
|
expect(capturedUIState.queueErrorMessage).toBe('Second error');
|
|
682
|
-
|
|
769
|
+
act(() => {
|
|
770
|
+
vi.advanceTimersByTime(2000);
|
|
771
|
+
});
|
|
683
772
|
rerender(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
684
773
|
expect(capturedUIState.queueErrorMessage).toBe('Second error');
|
|
685
774
|
// 5. Advance time past the 3 second timeout from the second message
|
|
686
|
-
|
|
775
|
+
act(() => {
|
|
776
|
+
vi.advanceTimersByTime(1000);
|
|
777
|
+
});
|
|
687
778
|
rerender(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
688
779
|
expect(capturedUIState.queueErrorMessage).toBeNull();
|
|
780
|
+
unmount();
|
|
689
781
|
});
|
|
690
782
|
});
|
|
691
783
|
describe('Terminal Height Calculation', () => {
|
|
692
784
|
const mockedMeasureElement = measureElement;
|
|
693
785
|
const mockedUseTerminalSize = useTerminalSize;
|
|
694
|
-
it('should prevent terminal height from being less than 1', () => {
|
|
786
|
+
it('should prevent terminal height from being less than 1', async () => {
|
|
695
787
|
const resizePtySpy = vi.spyOn(ShellExecutionService, 'resizePty');
|
|
696
788
|
// Arrange: Simulate a small terminal and a large footer
|
|
697
789
|
mockedUseTerminalSize.mockReturnValue({ columns: 80, rows: 5 });
|
|
@@ -705,61 +797,55 @@ describe('AppContainer State Management', () => {
|
|
|
705
797
|
cancelOngoingRequest: vi.fn(),
|
|
706
798
|
activePtyId: 'some-id',
|
|
707
799
|
});
|
|
708
|
-
render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
800
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
801
|
+
await act(async () => {
|
|
802
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
803
|
+
});
|
|
709
804
|
// Assert: The shell should be resized to a minimum height of 1, not a negative number.
|
|
710
805
|
// The old code would have tried to set a negative height.
|
|
711
806
|
expect(resizePtySpy).toHaveBeenCalled();
|
|
712
807
|
const lastCall = resizePtySpy.mock.calls[resizePtySpy.mock.calls.length - 1];
|
|
713
808
|
// Check the height argument specifically
|
|
714
809
|
expect(lastCall[2]).toBe(1);
|
|
810
|
+
unmount();
|
|
715
811
|
});
|
|
716
812
|
});
|
|
717
|
-
describe('Keyboard Input Handling', () => {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
slashCommands: [],
|
|
729
|
-
pendingHistoryItems: [],
|
|
730
|
-
commandContext: {},
|
|
731
|
-
shellConfirmationRequest: null,
|
|
732
|
-
confirmationRequest: null,
|
|
733
|
-
});
|
|
734
|
-
render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
735
|
-
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
|
736
|
-
});
|
|
737
|
-
it('should prevent exit command when text buffer has content', () => {
|
|
738
|
-
mockedUseTextBuffer.mockReturnValue({
|
|
739
|
-
text: 'some user input',
|
|
740
|
-
setText: vi.fn(),
|
|
741
|
-
});
|
|
742
|
-
const mockHandleSlashCommand = vi.fn();
|
|
743
|
-
mockedUseSlashCommandProcessor.mockReturnValue({
|
|
744
|
-
handleSlashCommand: mockHandleSlashCommand,
|
|
745
|
-
slashCommands: [],
|
|
746
|
-
pendingHistoryItems: [],
|
|
747
|
-
commandContext: {},
|
|
748
|
-
shellConfirmationRequest: null,
|
|
749
|
-
confirmationRequest: null,
|
|
813
|
+
describe('Keyboard Input Handling (CTRL+C / CTRL+D)', () => {
|
|
814
|
+
let handleGlobalKeypress;
|
|
815
|
+
let mockHandleSlashCommand;
|
|
816
|
+
let mockCancelOngoingRequest;
|
|
817
|
+
let rerender;
|
|
818
|
+
let unmount;
|
|
819
|
+
// Helper function to reduce boilerplate in tests
|
|
820
|
+
const setupKeypressTest = async () => {
|
|
821
|
+
const renderResult = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
822
|
+
await act(async () => {
|
|
823
|
+
vi.advanceTimersByTime(0);
|
|
750
824
|
});
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
825
|
+
rerender = () => renderResult.rerender(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
826
|
+
unmount = renderResult.unmount;
|
|
827
|
+
};
|
|
828
|
+
const pressKey = (key, times = 1) => {
|
|
829
|
+
for (let i = 0; i < times; i++) {
|
|
830
|
+
act(() => {
|
|
831
|
+
handleGlobalKeypress({
|
|
832
|
+
name: 'c',
|
|
833
|
+
ctrl: false,
|
|
834
|
+
meta: false,
|
|
835
|
+
shift: false,
|
|
836
|
+
...key,
|
|
837
|
+
});
|
|
838
|
+
});
|
|
839
|
+
rerender();
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
beforeEach(() => {
|
|
843
|
+
// Capture the keypress handler from the AppContainer
|
|
844
|
+
mockedUseKeypress.mockImplementation((callback) => {
|
|
845
|
+
handleGlobalKeypress = callback;
|
|
761
846
|
});
|
|
762
|
-
|
|
847
|
+
// Mock slash command handler
|
|
848
|
+
mockHandleSlashCommand = vi.fn();
|
|
763
849
|
mockedUseSlashCommandProcessor.mockReturnValue({
|
|
764
850
|
handleSlashCommand: mockHandleSlashCommand,
|
|
765
851
|
slashCommands: [],
|
|
@@ -768,72 +854,344 @@ describe('AppContainer State Management', () => {
|
|
|
768
854
|
shellConfirmationRequest: null,
|
|
769
855
|
confirmationRequest: null,
|
|
770
856
|
});
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
|
774
|
-
vi.useRealTimers();
|
|
775
|
-
});
|
|
776
|
-
it('should cancel ongoing request on first Ctrl+C', () => {
|
|
777
|
-
const mockCancelOngoingRequest = vi.fn();
|
|
857
|
+
// Mock request cancellation
|
|
858
|
+
mockCancelOngoingRequest = vi.fn();
|
|
778
859
|
mockedUseGeminiStream.mockReturnValue({
|
|
779
|
-
streamingState: '
|
|
860
|
+
streamingState: 'idle',
|
|
780
861
|
submitQuery: vi.fn(),
|
|
781
862
|
initError: null,
|
|
782
863
|
pendingHistoryItems: [],
|
|
783
864
|
thought: null,
|
|
784
865
|
cancelOngoingRequest: mockCancelOngoingRequest,
|
|
785
866
|
});
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
pendingHistoryItems: [],
|
|
791
|
-
commandContext: {},
|
|
792
|
-
shellConfirmationRequest: null,
|
|
793
|
-
confirmationRequest: null,
|
|
867
|
+
// Default empty text buffer
|
|
868
|
+
mockedUseTextBuffer.mockReturnValue({
|
|
869
|
+
text: '',
|
|
870
|
+
setText: vi.fn(),
|
|
794
871
|
});
|
|
795
|
-
render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
796
|
-
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
|
797
|
-
});
|
|
798
|
-
it('should reset Ctrl+C state after timeout', () => {
|
|
799
872
|
vi.useFakeTimers();
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
873
|
+
});
|
|
874
|
+
afterEach(() => {
|
|
875
|
+
vi.useRealTimers();
|
|
876
|
+
});
|
|
877
|
+
describe('CTRL+C', () => {
|
|
878
|
+
it('should cancel ongoing request on first press', async () => {
|
|
879
|
+
mockedUseGeminiStream.mockReturnValue({
|
|
880
|
+
streamingState: 'responding',
|
|
881
|
+
submitQuery: vi.fn(),
|
|
882
|
+
initError: null,
|
|
883
|
+
pendingHistoryItems: [],
|
|
884
|
+
thought: null,
|
|
885
|
+
cancelOngoingRequest: mockCancelOngoingRequest,
|
|
886
|
+
});
|
|
887
|
+
await setupKeypressTest();
|
|
888
|
+
pressKey({ name: 'c', ctrl: true });
|
|
889
|
+
expect(mockCancelOngoingRequest).toHaveBeenCalledTimes(1);
|
|
890
|
+
expect(mockHandleSlashCommand).not.toHaveBeenCalled();
|
|
891
|
+
unmount();
|
|
892
|
+
});
|
|
893
|
+
it('should quit on second press', async () => {
|
|
894
|
+
await setupKeypressTest();
|
|
895
|
+
pressKey({ name: 'c', ctrl: true }, 2);
|
|
896
|
+
expect(mockCancelOngoingRequest).toHaveBeenCalledTimes(2);
|
|
897
|
+
expect(mockHandleSlashCommand).toHaveBeenCalledWith('/quit');
|
|
898
|
+
unmount();
|
|
899
|
+
});
|
|
900
|
+
it('should reset press count after a timeout', async () => {
|
|
901
|
+
await setupKeypressTest();
|
|
902
|
+
pressKey({ name: 'c', ctrl: true });
|
|
903
|
+
expect(mockHandleSlashCommand).not.toHaveBeenCalled();
|
|
904
|
+
// Advance timer past the reset threshold
|
|
905
|
+
act(() => {
|
|
906
|
+
vi.advanceTimersByTime(1001);
|
|
907
|
+
});
|
|
908
|
+
pressKey({ name: 'c', ctrl: true });
|
|
909
|
+
expect(mockHandleSlashCommand).not.toHaveBeenCalled();
|
|
910
|
+
unmount();
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
describe('CTRL+D', () => {
|
|
914
|
+
it('should do nothing if text buffer is not empty', async () => {
|
|
915
|
+
mockedUseTextBuffer.mockReturnValue({
|
|
916
|
+
text: 'some text',
|
|
917
|
+
setText: vi.fn(),
|
|
918
|
+
});
|
|
919
|
+
await setupKeypressTest();
|
|
920
|
+
pressKey({ name: 'd', ctrl: true }, 2);
|
|
921
|
+
expect(mockHandleSlashCommand).not.toHaveBeenCalled();
|
|
922
|
+
unmount();
|
|
923
|
+
});
|
|
924
|
+
it('should quit on second press if buffer is empty', async () => {
|
|
925
|
+
await setupKeypressTest();
|
|
926
|
+
pressKey({ name: 'd', ctrl: true }, 2);
|
|
927
|
+
expect(mockHandleSlashCommand).toHaveBeenCalledWith('/quit');
|
|
928
|
+
unmount();
|
|
929
|
+
});
|
|
930
|
+
it('should reset press count after a timeout', async () => {
|
|
931
|
+
await setupKeypressTest();
|
|
932
|
+
pressKey({ name: 'd', ctrl: true });
|
|
933
|
+
expect(mockHandleSlashCommand).not.toHaveBeenCalled();
|
|
934
|
+
// Advance timer past the reset threshold
|
|
935
|
+
act(() => {
|
|
936
|
+
vi.advanceTimersByTime(1001);
|
|
937
|
+
});
|
|
938
|
+
pressKey({ name: 'd', ctrl: true });
|
|
939
|
+
expect(mockHandleSlashCommand).not.toHaveBeenCalled();
|
|
940
|
+
unmount();
|
|
941
|
+
});
|
|
942
|
+
});
|
|
943
|
+
});
|
|
944
|
+
describe('Copy Mode (CTRL+S)', () => {
|
|
945
|
+
let handleGlobalKeypress;
|
|
946
|
+
let rerender;
|
|
947
|
+
let unmount;
|
|
948
|
+
const setupCopyModeTest = async (isAlternateMode = false) => {
|
|
949
|
+
// Update settings for this test run
|
|
950
|
+
const testSettings = {
|
|
951
|
+
...mockSettings,
|
|
952
|
+
merged: {
|
|
953
|
+
...mockSettings.merged,
|
|
954
|
+
ui: {
|
|
955
|
+
...mockSettings.merged.ui,
|
|
956
|
+
useAlternateBuffer: isAlternateMode,
|
|
957
|
+
},
|
|
958
|
+
},
|
|
959
|
+
};
|
|
960
|
+
const renderResult = render(_jsx(AppContainer, { config: mockConfig, settings: testSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
961
|
+
await act(async () => {
|
|
962
|
+
vi.advanceTimersByTime(0);
|
|
963
|
+
});
|
|
964
|
+
rerender = () => renderResult.rerender(_jsx(AppContainer, { config: mockConfig, settings: testSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
965
|
+
unmount = renderResult.unmount;
|
|
966
|
+
};
|
|
967
|
+
beforeEach(() => {
|
|
968
|
+
mockStdout.write.mockClear();
|
|
969
|
+
mockedUseKeypress.mockImplementation((callback) => {
|
|
970
|
+
handleGlobalKeypress = callback;
|
|
808
971
|
});
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
|
972
|
+
vi.useFakeTimers();
|
|
973
|
+
});
|
|
974
|
+
afterEach(() => {
|
|
813
975
|
vi.useRealTimers();
|
|
814
976
|
});
|
|
977
|
+
describe.each([
|
|
978
|
+
{
|
|
979
|
+
isAlternateMode: false,
|
|
980
|
+
shouldEnable: false,
|
|
981
|
+
modeName: 'Normal Mode',
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
isAlternateMode: true,
|
|
985
|
+
shouldEnable: true,
|
|
986
|
+
modeName: 'Alternate Buffer Mode',
|
|
987
|
+
},
|
|
988
|
+
])('$modeName', ({ isAlternateMode, shouldEnable }) => {
|
|
989
|
+
it(`should ${shouldEnable ? 'toggle' : 'NOT toggle'} mouse off when Ctrl+S is pressed`, async () => {
|
|
990
|
+
await setupCopyModeTest(isAlternateMode);
|
|
991
|
+
mockStdout.write.mockClear(); // Clear initial enable call
|
|
992
|
+
act(() => {
|
|
993
|
+
handleGlobalKeypress({
|
|
994
|
+
name: 's',
|
|
995
|
+
ctrl: true,
|
|
996
|
+
meta: false,
|
|
997
|
+
shift: false,
|
|
998
|
+
paste: false,
|
|
999
|
+
sequence: '\x13',
|
|
1000
|
+
});
|
|
1001
|
+
});
|
|
1002
|
+
rerender();
|
|
1003
|
+
if (shouldEnable) {
|
|
1004
|
+
expect(disableMouseEvents).toHaveBeenCalled();
|
|
1005
|
+
}
|
|
1006
|
+
else {
|
|
1007
|
+
expect(disableMouseEvents).not.toHaveBeenCalled();
|
|
1008
|
+
}
|
|
1009
|
+
unmount();
|
|
1010
|
+
});
|
|
1011
|
+
if (shouldEnable) {
|
|
1012
|
+
it('should toggle mouse back on when Ctrl+S is pressed again', async () => {
|
|
1013
|
+
await setupCopyModeTest(isAlternateMode);
|
|
1014
|
+
mockStdout.write.mockClear();
|
|
1015
|
+
// Turn it on (disable mouse)
|
|
1016
|
+
act(() => {
|
|
1017
|
+
handleGlobalKeypress({
|
|
1018
|
+
name: 's',
|
|
1019
|
+
ctrl: true,
|
|
1020
|
+
meta: false,
|
|
1021
|
+
shift: false,
|
|
1022
|
+
paste: false,
|
|
1023
|
+
sequence: '\x13',
|
|
1024
|
+
});
|
|
1025
|
+
});
|
|
1026
|
+
rerender();
|
|
1027
|
+
expect(disableMouseEvents).toHaveBeenCalled();
|
|
1028
|
+
// Turn it off (enable mouse)
|
|
1029
|
+
act(() => {
|
|
1030
|
+
handleGlobalKeypress({
|
|
1031
|
+
name: 'any', // Any key should exit copy mode
|
|
1032
|
+
ctrl: false,
|
|
1033
|
+
meta: false,
|
|
1034
|
+
shift: false,
|
|
1035
|
+
paste: false,
|
|
1036
|
+
sequence: 'a',
|
|
1037
|
+
});
|
|
1038
|
+
});
|
|
1039
|
+
rerender();
|
|
1040
|
+
expect(enableMouseEvents).toHaveBeenCalled();
|
|
1041
|
+
unmount();
|
|
1042
|
+
});
|
|
1043
|
+
it('should exit copy mode on any key press', async () => {
|
|
1044
|
+
await setupCopyModeTest(isAlternateMode);
|
|
1045
|
+
// Enter copy mode
|
|
1046
|
+
act(() => {
|
|
1047
|
+
handleGlobalKeypress({
|
|
1048
|
+
name: 's',
|
|
1049
|
+
ctrl: true,
|
|
1050
|
+
meta: false,
|
|
1051
|
+
shift: false,
|
|
1052
|
+
paste: false,
|
|
1053
|
+
sequence: '\x13',
|
|
1054
|
+
});
|
|
1055
|
+
});
|
|
1056
|
+
rerender();
|
|
1057
|
+
mockStdout.write.mockClear();
|
|
1058
|
+
// Press any other key
|
|
1059
|
+
act(() => {
|
|
1060
|
+
handleGlobalKeypress({
|
|
1061
|
+
name: 'a',
|
|
1062
|
+
ctrl: false,
|
|
1063
|
+
meta: false,
|
|
1064
|
+
shift: false,
|
|
1065
|
+
paste: false,
|
|
1066
|
+
sequence: 'a',
|
|
1067
|
+
});
|
|
1068
|
+
});
|
|
1069
|
+
rerender();
|
|
1070
|
+
// Should have re-enabled mouse
|
|
1071
|
+
expect(enableMouseEvents).toHaveBeenCalled();
|
|
1072
|
+
unmount();
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
815
1076
|
});
|
|
816
1077
|
describe('Model Dialog Integration', () => {
|
|
817
|
-
it('should provide isModelDialogOpen in the UIStateContext', () => {
|
|
1078
|
+
it('should provide isModelDialogOpen in the UIStateContext', async () => {
|
|
818
1079
|
mockedUseModelCommand.mockReturnValue({
|
|
819
1080
|
isModelDialogOpen: true,
|
|
820
1081
|
openModelDialog: vi.fn(),
|
|
821
1082
|
closeModelDialog: vi.fn(),
|
|
822
1083
|
});
|
|
823
|
-
render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1084
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1085
|
+
await act(async () => {
|
|
1086
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1087
|
+
});
|
|
824
1088
|
expect(capturedUIState.isModelDialogOpen).toBe(true);
|
|
1089
|
+
unmount();
|
|
825
1090
|
});
|
|
826
|
-
it('should provide model dialog actions in the UIActionsContext', () => {
|
|
1091
|
+
it('should provide model dialog actions in the UIActionsContext', async () => {
|
|
827
1092
|
const mockCloseModelDialog = vi.fn();
|
|
828
1093
|
mockedUseModelCommand.mockReturnValue({
|
|
829
1094
|
isModelDialogOpen: false,
|
|
830
1095
|
openModelDialog: vi.fn(),
|
|
831
1096
|
closeModelDialog: mockCloseModelDialog,
|
|
832
1097
|
});
|
|
833
|
-
render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1098
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1099
|
+
await act(async () => {
|
|
1100
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1101
|
+
});
|
|
834
1102
|
// Verify that the actions are correctly passed through context
|
|
835
|
-
|
|
1103
|
+
act(() => {
|
|
1104
|
+
capturedUIActions.closeModelDialog();
|
|
1105
|
+
});
|
|
836
1106
|
expect(mockCloseModelDialog).toHaveBeenCalled();
|
|
1107
|
+
unmount();
|
|
1108
|
+
});
|
|
1109
|
+
});
|
|
1110
|
+
describe('CoreEvents Integration', () => {
|
|
1111
|
+
it('subscribes to UserFeedback and drains backlog on mount', async () => {
|
|
1112
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1113
|
+
await act(async () => {
|
|
1114
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1115
|
+
});
|
|
1116
|
+
expect(mockCoreEvents.on).toHaveBeenCalledWith(CoreEvent.UserFeedback, expect.any(Function));
|
|
1117
|
+
expect(mockCoreEvents.drainFeedbackBacklog).toHaveBeenCalledTimes(1);
|
|
1118
|
+
unmount();
|
|
1119
|
+
});
|
|
1120
|
+
it('unsubscribes from UserFeedback on unmount', async () => {
|
|
1121
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1122
|
+
await act(async () => {
|
|
1123
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1124
|
+
});
|
|
1125
|
+
unmount();
|
|
1126
|
+
expect(mockCoreEvents.off).toHaveBeenCalledWith(CoreEvent.UserFeedback, expect.any(Function));
|
|
1127
|
+
});
|
|
1128
|
+
it('adds history item when UserFeedback event is received', async () => {
|
|
1129
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1130
|
+
await act(async () => {
|
|
1131
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1132
|
+
});
|
|
1133
|
+
// Get the registered handler
|
|
1134
|
+
const handler = mockCoreEvents.on.mock.calls.find((call) => call[0] === CoreEvent.UserFeedback)?.[1];
|
|
1135
|
+
expect(handler).toBeDefined();
|
|
1136
|
+
// Simulate an event
|
|
1137
|
+
const payload = {
|
|
1138
|
+
severity: 'error',
|
|
1139
|
+
message: 'Test error message',
|
|
1140
|
+
};
|
|
1141
|
+
act(() => {
|
|
1142
|
+
handler(payload);
|
|
1143
|
+
});
|
|
1144
|
+
expect(mockedUseHistory().addItem).toHaveBeenCalledWith(expect.objectContaining({
|
|
1145
|
+
type: 'error',
|
|
1146
|
+
text: 'Test error message',
|
|
1147
|
+
}), expect.any(Number));
|
|
1148
|
+
unmount();
|
|
1149
|
+
});
|
|
1150
|
+
it('updates currentModel when ModelChanged event is received', async () => {
|
|
1151
|
+
// Arrange: Mock initial model
|
|
1152
|
+
vi.spyOn(mockConfig, 'getModel').mockReturnValue('initial-model');
|
|
1153
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1154
|
+
// Verify initial model
|
|
1155
|
+
await act(async () => {
|
|
1156
|
+
await vi.waitFor(() => {
|
|
1157
|
+
expect(capturedUIState?.currentModel).toBe('initial-model');
|
|
1158
|
+
});
|
|
1159
|
+
});
|
|
1160
|
+
// Get the registered handler for ModelChanged
|
|
1161
|
+
const handler = mockCoreEvents.on.mock.calls.find((call) => call[0] === CoreEvent.ModelChanged)?.[1];
|
|
1162
|
+
expect(handler).toBeDefined();
|
|
1163
|
+
// Act: Simulate ModelChanged event
|
|
1164
|
+
act(() => {
|
|
1165
|
+
handler({ model: 'new-model' });
|
|
1166
|
+
});
|
|
1167
|
+
// Assert: Verify model is updated
|
|
1168
|
+
expect(capturedUIState.currentModel).toBe('new-model');
|
|
1169
|
+
unmount();
|
|
1170
|
+
});
|
|
1171
|
+
});
|
|
1172
|
+
describe('Shell Interaction', () => {
|
|
1173
|
+
it('should not crash if resizing the pty fails', async () => {
|
|
1174
|
+
const resizePtySpy = vi
|
|
1175
|
+
.spyOn(ShellExecutionService, 'resizePty')
|
|
1176
|
+
.mockImplementation(() => {
|
|
1177
|
+
throw new Error('Cannot resize a pty that has already exited');
|
|
1178
|
+
});
|
|
1179
|
+
mockedUseGeminiStream.mockReturnValue({
|
|
1180
|
+
streamingState: 'idle',
|
|
1181
|
+
submitQuery: vi.fn(),
|
|
1182
|
+
initError: null,
|
|
1183
|
+
pendingHistoryItems: [],
|
|
1184
|
+
thought: null,
|
|
1185
|
+
cancelOngoingRequest: vi.fn(),
|
|
1186
|
+
activePtyId: 'some-pty-id', // Make sure activePtyId is set
|
|
1187
|
+
});
|
|
1188
|
+
// The main assertion is that the render does not throw.
|
|
1189
|
+
const { unmount } = render(_jsx(AppContainer, { config: mockConfig, settings: mockSettings, version: "1.0.0", initializationResult: mockInitResult }));
|
|
1190
|
+
await act(async () => {
|
|
1191
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1192
|
+
});
|
|
1193
|
+
expect(resizePtySpy).toHaveBeenCalled();
|
|
1194
|
+
unmount();
|
|
837
1195
|
});
|
|
838
1196
|
});
|
|
839
1197
|
});
|