@machina.ai/cell-cli 1.36.0-rc1 → 1.38.1-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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/package.json +4 -4
- package/dist/src/acp/acpClient.js +297 -32
- package/dist/src/acp/acpClient.js.map +1 -1
- package/dist/src/acp/acpClient.test.js +419 -19
- package/dist/src/acp/acpClient.test.js.map +1 -1
- package/dist/src/acp/acpResume.test.js +8 -0
- package/dist/src/acp/acpResume.test.js.map +1 -1
- package/dist/src/acp/commandHandler.js +4 -0
- package/dist/src/acp/commandHandler.js.map +1 -1
- package/dist/src/acp/commandHandler.test.js +4 -0
- package/dist/src/acp/commandHandler.test.js.map +1 -1
- package/dist/src/acp/commands/about.d.ts +11 -0
- package/dist/src/acp/commands/about.js +53 -0
- package/dist/src/acp/commands/about.js.map +1 -0
- package/dist/src/acp/commands/extensions.js +1 -1
- package/dist/src/acp/commands/extensions.js.map +1 -1
- package/dist/src/acp/commands/help.d.ts +14 -0
- package/dist/src/acp/commands/help.js +35 -0
- package/dist/src/acp/commands/help.js.map +1 -0
- package/dist/src/acp/commands/help.test.d.ts +6 -0
- package/dist/src/acp/commands/help.test.js +40 -0
- package/dist/src/acp/commands/help.test.js.map +1 -0
- package/dist/src/acp/commands/restore.js +2 -2
- package/dist/src/acp/commands/restore.js.map +1 -1
- package/dist/src/commands/extensions/new.js +1 -1
- package/dist/src/commands/extensions/new.js.map +1 -1
- package/dist/src/commands/mcp/list.js +2 -2
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp.test.js +1 -1
- package/dist/src/commands/mcp.test.js.map +1 -1
- package/dist/src/commands/skills/list.js +5 -8
- package/dist/src/commands/skills/list.js.map +1 -1
- package/dist/src/commands/skills/list.test.js +17 -13
- package/dist/src/commands/skills/list.test.js.map +1 -1
- package/dist/src/config/config.js +22 -9
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +121 -36
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/extension-manager-permissions.test.js +1 -1
- package/dist/src/config/extension-manager-permissions.test.js.map +1 -1
- package/dist/src/config/extension-manager-themes.spec.js +1 -0
- package/dist/src/config/extension-manager-themes.spec.js.map +1 -1
- package/dist/src/config/extension-manager.test.js +1 -1
- package/dist/src/config/extension-manager.test.js.map +1 -1
- package/dist/src/config/extension.js +1 -1
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/extensions/github.js +1 -1
- package/dist/src/config/extensions/github.js.map +1 -1
- package/dist/src/config/footerItems.d.ts +4 -0
- package/dist/src/config/footerItems.js +12 -2
- package/dist/src/config/footerItems.js.map +1 -1
- package/dist/src/config/footerItems.test.js +129 -72
- package/dist/src/config/footerItems.test.js.map +1 -1
- package/dist/src/config/policy-engine.integration.test.js +1 -3
- package/dist/src/config/policy-engine.integration.test.js.map +1 -1
- package/dist/src/config/policy.d.ts +1 -1
- package/dist/src/config/policy.js +2 -2
- package/dist/src/config/policy.js.map +1 -1
- package/dist/src/config/settings.js +19 -3
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +272 -53
- package/dist/src/config/settingsSchema.js +262 -48
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.js +22 -4
- package/dist/src/config/settingsSchema.test.js.map +1 -1
- package/dist/src/config/workspace-policy-cli.test.js +7 -7
- package/dist/src/config/workspace-policy-cli.test.js.map +1 -1
- package/dist/src/gemini.js +24 -7
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +74 -4
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/gemini_cleanup.test.js +69 -4
- package/dist/src/gemini_cleanup.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/integration-tests/modelSteering.test.js +1 -1
- package/dist/src/integration-tests/modelSteering.test.js.map +1 -1
- package/dist/src/interactiveCli.js +4 -2
- package/dist/src/interactiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.d.ts +1 -1
- package/dist/src/nonInteractiveCli.js +11 -2
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.js +4 -2
- package/dist/src/nonInteractiveCli.test.js.map +1 -1
- package/dist/src/nonInteractiveCliAgentSession.d.ts +16 -0
- package/dist/src/nonInteractiveCliAgentSession.js +484 -0
- package/dist/src/nonInteractiveCliAgentSession.js.map +1 -0
- package/dist/src/nonInteractiveCliAgentSession.test.js +1837 -0
- package/dist/src/nonInteractiveCliAgentSession.test.js.map +1 -0
- package/dist/src/services/BuiltinCommandLoader.js +4 -2
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/test-utils/mockCommandContext.js +1 -0
- package/dist/src/test-utils/mockCommandContext.js.map +1 -1
- package/dist/src/test-utils/mockConfig.js +16 -0
- package/dist/src/test-utils/mockConfig.js.map +1 -1
- package/dist/src/test-utils/mockSpinner.d.ts +6 -0
- package/dist/src/test-utils/mockSpinner.js +21 -0
- package/dist/src/test-utils/mockSpinner.js.map +1 -0
- package/dist/src/test-utils/render.d.ts +8 -1
- package/dist/src/test-utils/render.js +37 -11
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/ui/App.test.js +1 -1
- package/dist/src/ui/App.test.js.map +1 -1
- package/dist/src/ui/AppContainer.js +225 -99
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +50 -38
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/commands/chatCommand.js +15 -5
- package/dist/src/ui/commands/chatCommand.js.map +1 -1
- package/dist/src/ui/commands/clearCommand.js +3 -1
- package/dist/src/ui/commands/clearCommand.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 +22 -11
- package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
- package/dist/src/ui/commands/marketplaceCommand.d.ts +7 -0
- package/dist/src/ui/commands/marketplaceCommand.js +135 -0
- package/dist/src/ui/commands/marketplaceCommand.js.map +1 -0
- package/dist/src/ui/commands/mcpCommand.js +26 -7
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.test.js +26 -0
- package/dist/src/ui/commands/mcpCommand.test.js.map +1 -1
- package/dist/src/ui/commands/planCommand.js +9 -0
- package/dist/src/ui/commands/planCommand.js.map +1 -1
- package/dist/src/ui/commands/planCommand.test.js +29 -0
- package/dist/src/ui/commands/planCommand.test.js.map +1 -1
- package/dist/src/ui/commands/restoreCommand.js +1 -1
- package/dist/src/ui/commands/restoreCommand.js.map +1 -1
- package/dist/src/ui/commands/rewindCommand.js +3 -1
- package/dist/src/ui/commands/rewindCommand.js.map +1 -1
- package/dist/src/ui/commands/rewindCommand.test.js +1 -1
- package/dist/src/ui/commands/rewindCommand.test.js.map +1 -1
- package/dist/src/ui/commands/setupGithubCommand.js +5 -5
- package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
- package/dist/src/ui/commands/skillsCommand.js +11 -1
- package/dist/src/ui/commands/skillsCommand.js.map +1 -1
- package/dist/src/ui/commands/skillsCommand.test.js +1 -0
- package/dist/src/ui/commands/skillsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/{shellsCommand.d.ts → tasksCommand.d.ts} +1 -1
- package/dist/src/ui/commands/{shellsCommand.js → tasksCommand.js} +6 -6
- package/dist/src/ui/commands/tasksCommand.js.map +1 -0
- package/dist/src/ui/commands/tasksCommand.test.js +30 -0
- package/dist/src/ui/commands/tasksCommand.test.js.map +1 -0
- package/dist/src/ui/commands/types.d.ts +9 -1
- package/dist/src/ui/components/AnsiOutput.js +7 -5
- package/dist/src/ui/components/AnsiOutput.js.map +1 -1
- package/dist/src/ui/components/AnsiOutput.test.js +13 -0
- package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
- package/dist/src/ui/components/AppHeader.js +11 -11
- package/dist/src/ui/components/AppHeader.js.map +1 -1
- package/dist/src/ui/components/AppHeader.test.js +6 -2
- package/dist/src/ui/components/AppHeader.test.js.map +1 -1
- package/dist/src/ui/components/AsciiArt.d.ts +6 -6
- package/dist/src/ui/components/AsciiArt.js +6 -6
- package/dist/src/ui/components/AskUserDialog.js +13 -13
- package/dist/src/ui/components/AskUserDialog.js.map +1 -1
- package/dist/src/ui/components/AskUserDialog.test.js +31 -0
- package/dist/src/ui/components/AskUserDialog.test.js.map +1 -1
- package/dist/src/ui/components/BackgroundTaskDisplay.d.ts +16 -0
- package/dist/src/ui/components/{BackgroundShellDisplay.js → BackgroundTaskDisplay.js} +12 -12
- package/dist/src/ui/components/BackgroundTaskDisplay.js.map +1 -0
- package/dist/src/ui/components/{BackgroundShellDisplay.test.js → BackgroundTaskDisplay.test.js} +26 -26
- package/dist/src/ui/components/BackgroundTaskDisplay.test.js.map +1 -0
- package/dist/src/ui/components/Composer.js +20 -208
- package/dist/src/ui/components/Composer.js.map +1 -1
- package/dist/src/ui/components/Composer.test.js +22 -17
- package/dist/src/ui/components/Composer.test.js.map +1 -1
- package/dist/src/ui/components/ContextSummaryDisplay.js +3 -1
- package/dist/src/ui/components/ContextSummaryDisplay.js.map +1 -1
- package/dist/src/ui/components/CopyModeWarning.js +3 -6
- package/dist/src/ui/components/CopyModeWarning.js.map +1 -1
- package/dist/src/ui/components/CopyModeWarning.test.js +7 -8
- package/dist/src/ui/components/CopyModeWarning.test.js.map +1 -1
- package/dist/src/ui/components/ExitPlanModeDialog.js +9 -0
- package/dist/src/ui/components/ExitPlanModeDialog.js.map +1 -1
- package/dist/src/ui/components/ExitPlanModeDialog.test.js +15 -3
- package/dist/src/ui/components/ExitPlanModeDialog.test.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +7 -8
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.js +36 -9
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/Footer.test.js +85 -6
- package/dist/src/ui/components/Footer.test.js.map +1 -1
- package/dist/src/ui/components/FooterConfigDialog.js +1 -0
- package/dist/src/ui/components/FooterConfigDialog.js.map +1 -1
- package/dist/src/ui/components/FooterConfigDialog.test.js +1 -1
- package/dist/src/ui/components/Help.test.js +1 -1
- package/dist/src/ui/components/Help.test.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.d.ts +2 -0
- package/dist/src/ui/components/HistoryItemDisplay.js +14 -12
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.d.ts +10 -5
- package/dist/src/ui/components/InputPrompt.js +195 -90
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.d.ts +12 -1
- package/dist/src/ui/components/InputPrompt.test.js +370 -160
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.js +1 -2
- package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.test.js +7 -0
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/components/MainContent.d.ts +1 -1
- package/dist/src/ui/components/MainContent.js +105 -34
- package/dist/src/ui/components/MainContent.js.map +1 -1
- package/dist/src/ui/components/MainContent.test.js +12 -9
- package/dist/src/ui/components/MainContent.test.js.map +1 -1
- package/dist/src/ui/components/MemoryUsageDisplay.d.ts +1 -0
- package/dist/src/ui/components/MemoryUsageDisplay.js +5 -2
- package/dist/src/ui/components/MemoryUsageDisplay.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.js +50 -72
- package/dist/src/ui/components/ModelDialog.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.test.js +1 -0
- package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
- package/dist/src/ui/components/ModelQuotaDisplay.d.ts +18 -0
- package/dist/src/ui/components/ModelQuotaDisplay.js +104 -0
- package/dist/src/ui/components/ModelQuotaDisplay.js.map +1 -0
- package/dist/src/ui/components/ModelQuotaDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/ModelQuotaDisplay.test.js +62 -0
- package/dist/src/ui/components/ModelQuotaDisplay.test.js.map +1 -0
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/ProgressBar.d.ts +13 -0
- package/dist/src/ui/components/ProgressBar.js +17 -0
- package/dist/src/ui/components/ProgressBar.js.map +1 -0
- package/dist/src/ui/components/ProgressBar.test.d.ts +6 -0
- package/dist/src/ui/components/ProgressBar.test.js +28 -0
- package/dist/src/ui/components/ProgressBar.test.js.map +1 -0
- package/dist/src/ui/components/StatsDisplay.d.ts +2 -2
- package/dist/src/ui/components/StatsDisplay.js +47 -128
- package/dist/src/ui/components/StatsDisplay.js.map +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js +65 -136
- package/dist/src/ui/components/StatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/StatusDisplay.js +1 -1
- package/dist/src/ui/components/StatusDisplay.js.map +1 -1
- package/dist/src/ui/components/StatusDisplay.test.js +3 -3
- package/dist/src/ui/components/StatusDisplay.test.js.map +1 -1
- package/dist/src/ui/components/StatusRow.d.ts +32 -0
- package/dist/src/ui/components/StatusRow.js +180 -0
- package/dist/src/ui/components/StatusRow.js.map +1 -0
- package/dist/src/ui/components/StatusRow.test.d.ts +6 -0
- package/dist/src/ui/components/StatusRow.test.js +99 -0
- package/dist/src/ui/components/StatusRow.test.js.map +1 -0
- package/dist/src/ui/components/ToastDisplay.d.ts +2 -1
- package/dist/src/ui/components/ToastDisplay.js +7 -5
- package/dist/src/ui/components/ToastDisplay.js.map +1 -1
- package/dist/src/ui/components/ToastDisplay.test.js +34 -20
- package/dist/src/ui/components/ToastDisplay.test.js.map +1 -1
- package/dist/src/ui/components/ToolConfirmationQueue.js +24 -9
- package/dist/src/ui/components/ToolConfirmationQueue.js.map +1 -1
- package/dist/src/ui/components/ToolConfirmationQueue.test.js +4 -6
- package/dist/src/ui/components/ToolConfirmationQueue.test.js.map +1 -1
- package/dist/src/ui/components/UserIdentity.js +8 -5
- package/dist/src/ui/components/UserIdentity.js.map +1 -1
- package/dist/src/ui/components/messages/DenseToolMessage.d.ts +13 -0
- package/dist/src/ui/components/messages/DenseToolMessage.js +270 -0
- package/dist/src/ui/components/messages/DenseToolMessage.js.map +1 -0
- package/dist/src/ui/components/messages/DenseToolMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/DenseToolMessage.test.js +383 -0
- package/dist/src/ui/components/messages/DenseToolMessage.test.js.map +1 -0
- package/dist/src/ui/components/messages/DiffRenderer.d.ts +18 -0
- package/dist/src/ui/components/messages/DiffRenderer.js +54 -34
- package/dist/src/ui/components/messages/DiffRenderer.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js +12 -6
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
- package/dist/src/ui/components/messages/InfoMessage.d.ts +1 -0
- package/dist/src/ui/components/messages/InfoMessage.js +2 -2
- package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
- package/dist/src/ui/components/messages/RedirectionConfirmation.test.js +1 -1
- package/dist/src/ui/components/messages/RedirectionConfirmation.test.js.map +1 -1
- package/dist/src/ui/components/messages/ShellToolMessage.test.js +44 -33
- package/dist/src/ui/components/messages/ShellToolMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/SubagentGroupDisplay.js +3 -2
- package/dist/src/ui/components/messages/SubagentGroupDisplay.js.map +1 -1
- package/dist/src/ui/components/messages/SubagentGroupDisplay.test.js +1 -1
- package/dist/src/ui/components/messages/SubagentGroupDisplay.test.js.map +1 -1
- package/dist/src/ui/components/messages/SubagentHistoryMessage.d.ts +13 -0
- package/dist/src/ui/components/messages/SubagentHistoryMessage.js +4 -0
- package/dist/src/ui/components/messages/SubagentHistoryMessage.js.map +1 -0
- package/dist/src/ui/components/messages/SubagentHistoryMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/SubagentHistoryMessage.test.js +68 -0
- package/dist/src/ui/components/messages/SubagentHistoryMessage.test.js.map +1 -0
- package/dist/src/ui/components/messages/SubagentProgressDisplay.d.ts +2 -1
- package/dist/src/ui/components/messages/SubagentProgressDisplay.js +2 -2
- package/dist/src/ui/components/messages/SubagentProgressDisplay.js.map +1 -1
- package/dist/src/ui/components/messages/SubagentProgressDisplay.test.js +0 -4
- package/dist/src/ui/components/messages/SubagentProgressDisplay.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.d.ts +1 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +108 -70
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +40 -25
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.compact.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolGroupMessage.compact.test.js +147 -0
- package/dist/src/ui/components/messages/ToolGroupMessage.compact.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolGroupMessage.d.ts +3 -0
- package/dist/src/ui/components/messages/ToolGroupMessage.js +219 -52
- package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +55 -3
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.test.js +8 -7
- package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolOverflowConsistencyChecks.test.js +1 -1
- package/dist/src/ui/components/messages/ToolOverflowConsistencyChecks.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolResultDisplay.js +57 -15
- package/dist/src/ui/components/messages/ToolResultDisplay.js.map +1 -1
- package/dist/src/ui/components/messages/ToolResultDisplay.test.js +66 -3
- package/dist/src/ui/components/messages/ToolResultDisplay.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolResultDisplayOverflow.test.js +5 -4
- package/dist/src/ui/components/messages/ToolResultDisplayOverflow.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolStickyHeaderRegression.test.js +3 -3
- package/dist/src/ui/components/messages/ToolStickyHeaderRegression.test.js.map +1 -1
- package/dist/src/ui/components/messages/TopicMessage.d.ts +15 -0
- package/dist/src/ui/components/messages/TopicMessage.js +56 -0
- package/dist/src/ui/components/messages/TopicMessage.js.map +1 -0
- package/dist/src/ui/components/messages/TopicMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/TopicMessage.test.js +77 -0
- package/dist/src/ui/components/messages/TopicMessage.test.js.map +1 -0
- package/dist/src/ui/components/shared/MaxSizedBox.d.ts +1 -0
- package/dist/src/ui/components/shared/MaxSizedBox.js +10 -7
- package/dist/src/ui/components/shared/MaxSizedBox.js.map +1 -1
- package/dist/src/ui/components/shared/Scrollable.d.ts +3 -0
- package/dist/src/ui/components/shared/Scrollable.js +6 -2
- package/dist/src/ui/components/shared/Scrollable.js.map +1 -1
- package/dist/src/ui/components/shared/ScrollableList.d.ts +9 -12
- package/dist/src/ui/components/shared/ScrollableList.js +2 -2
- package/dist/src/ui/components/shared/ScrollableList.js.map +1 -1
- package/dist/src/ui/components/shared/VirtualizedList.d.ts +13 -1
- package/dist/src/ui/components/shared/VirtualizedList.js +148 -37
- package/dist/src/ui/components/shared/VirtualizedList.js.map +1 -1
- package/dist/src/ui/components/shared/VirtualizedList.test.js +1 -10
- package/dist/src/ui/components/shared/VirtualizedList.test.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.d.ts +1 -0
- package/dist/src/ui/components/shared/text-buffer.js +19 -21
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionDetails.d.ts +4 -1
- package/dist/src/ui/components/views/ExtensionDetails.js +14 -4
- package/dist/src/ui/components/views/ExtensionDetails.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionDetails.test.js +25 -1
- package/dist/src/ui/components/views/ExtensionDetails.test.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionRegistryView.js +19 -5
- package/dist/src/ui/components/views/ExtensionRegistryView.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionRegistryView.test.js +38 -0
- package/dist/src/ui/components/views/ExtensionRegistryView.test.js.map +1 -1
- package/dist/src/ui/components/views/SkillsList.js +2 -1
- package/dist/src/ui/components/views/SkillsList.js.map +1 -1
- package/dist/src/ui/components/views/SkillsList.test.js +3 -1
- package/dist/src/ui/components/views/SkillsList.test.js.map +1 -1
- package/dist/src/ui/constants/tips.js +2 -2
- package/dist/src/ui/constants/tips.js.map +1 -1
- package/dist/src/ui/constants.d.ts +6 -0
- package/dist/src/ui/constants.js +15 -0
- package/dist/src/ui/constants.js.map +1 -1
- package/dist/src/ui/contexts/InputContext.d.ts +17 -0
- package/dist/src/ui/contexts/InputContext.js +15 -0
- package/dist/src/ui/contexts/InputContext.js.map +1 -0
- package/dist/src/ui/contexts/KeypressContext.js +1 -1
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +25 -1
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/ScrollProvider.js +25 -3
- package/dist/src/ui/contexts/ScrollProvider.js.map +1 -1
- package/dist/src/ui/contexts/ScrollProvider.test.js +100 -0
- package/dist/src/ui/contexts/ScrollProvider.test.js.map +1 -1
- package/dist/src/ui/contexts/SessionContext.d.ts +2 -2
- package/dist/src/ui/contexts/SessionContext.js.map +1 -1
- package/dist/src/ui/contexts/ToolActionsContext.d.ts +6 -0
- package/dist/src/ui/contexts/ToolActionsContext.js +19 -11
- package/dist/src/ui/contexts/ToolActionsContext.js.map +1 -1
- package/dist/src/ui/contexts/ToolActionsContext.test.js +90 -7
- package/dist/src/ui/contexts/ToolActionsContext.test.js.map +1 -1
- package/dist/src/ui/contexts/UIActionsContext.d.ts +4 -3
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/contexts/UIStateContext.d.ts +10 -16
- package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js +2 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor_agents.test.js +2 -1
- package/dist/src/ui/hooks/atCommandProcessor_agents.test.js.map +1 -1
- package/dist/src/ui/hooks/shellReducer.d.ts +12 -10
- package/dist/src/ui/hooks/shellReducer.js +67 -37
- package/dist/src/ui/hooks/shellReducer.js.map +1 -1
- package/dist/src/ui/hooks/shellReducer.test.js +207 -36
- package/dist/src/ui/hooks/shellReducer.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.d.ts +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.test.js +1 -1
- package/dist/src/ui/hooks/toolMapping.js +7 -0
- package/dist/src/ui/hooks/toolMapping.js.map +1 -1
- package/dist/src/ui/hooks/useAlternateBuffer.js +6 -1
- package/dist/src/ui/hooks/useAlternateBuffer.js.map +1 -1
- package/dist/src/ui/hooks/useAlternateBuffer.test.js +5 -0
- package/dist/src/ui/hooks/useAlternateBuffer.test.js.map +1 -1
- package/dist/src/ui/hooks/useAnimatedScrollbar.js +2 -2
- package/dist/src/ui/hooks/useAnimatedScrollbar.js.map +1 -1
- package/dist/src/ui/hooks/useAtCompletion.js +1 -1
- package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useBackgroundTaskManager.d.ts +22 -0
- package/dist/src/ui/hooks/useBackgroundTaskManager.js +58 -0
- package/dist/src/ui/hooks/useBackgroundTaskManager.js.map +1 -0
- package/dist/src/ui/hooks/{useBackgroundShellManager.test.js → useBackgroundTaskManager.test.js} +50 -50
- package/dist/src/ui/hooks/useBackgroundTaskManager.test.js.map +1 -0
- package/dist/src/ui/hooks/useBanner.d.ts +1 -0
- package/dist/src/ui/hooks/useBanner.js +16 -9
- package/dist/src/ui/hooks/useBanner.js.map +1 -1
- package/dist/src/ui/hooks/useBanner.test.js +7 -4
- package/dist/src/ui/hooks/useBanner.test.js.map +1 -1
- package/dist/src/ui/hooks/useBatchedScroll.js +2 -2
- package/dist/src/ui/hooks/useBatchedScroll.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.d.ts +2 -1
- package/dist/src/ui/hooks/useCommandCompletion.js +13 -3
- package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.d.ts +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.js +82 -6
- package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useComposerStatus.d.ts +21 -0
- package/dist/src/ui/hooks/useComposerStatus.js +78 -0
- package/dist/src/ui/hooks/useComposerStatus.js.map +1 -0
- package/dist/src/ui/hooks/useConsoleMessages.test.js +2 -2
- package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
- package/dist/src/ui/hooks/useExecutionLifecycle.d.ts +28 -0
- package/dist/src/ui/hooks/{shellCommandProcessor.js → useExecutionLifecycle.js} +140 -58
- package/dist/src/ui/hooks/useExecutionLifecycle.js.map +1 -0
- package/dist/src/ui/hooks/useExecutionLifecycle.test.d.ts +6 -0
- package/dist/src/ui/hooks/{shellCommandProcessor.test.js → useExecutionLifecycle.test.js} +123 -81
- package/dist/src/ui/hooks/useExecutionLifecycle.test.js.map +1 -0
- package/dist/src/ui/hooks/useFolderTrust.js +1 -1
- package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
- package/dist/src/ui/hooks/useFolderTrust.test.js +1 -1
- package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.d.ts +6 -6
- package/dist/src/ui/hooks/useGeminiStream.js +140 -38
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.js +176 -22
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.js +2 -2
- package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.js +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +10 -0
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/usePermissionsModifyTrust.js +2 -2
- package/dist/src/ui/hooks/usePermissionsModifyTrust.js.map +1 -1
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +1 -1
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js +4 -2
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/useSessionBrowser.d.ts +1 -1
- package/dist/src/ui/hooks/useSessionBrowser.js +2 -2
- package/dist/src/ui/hooks/useSessionBrowser.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.d.ts +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.js +37 -63
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.d.ts +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +57 -47
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.d.ts +2 -1
- package/dist/src/ui/hooks/useToolScheduler.js +55 -1
- package/dist/src/ui/hooks/useToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +107 -9
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/key/keyBindings.d.ts +9 -1
- package/dist/src/ui/key/keyBindings.js +40 -3
- package/dist/src/ui/key/keyBindings.js.map +1 -1
- package/dist/src/ui/key/keyMatchers.test.js +12 -2
- package/dist/src/ui/key/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/layouts/DefaultAppLayout.js +8 -6
- package/dist/src/ui/layouts/DefaultAppLayout.js.map +1 -1
- package/dist/src/ui/layouts/DefaultAppLayout.test.js +27 -22
- package/dist/src/ui/layouts/DefaultAppLayout.test.js.map +1 -1
- package/dist/src/ui/noninteractive/nonInteractiveUi.js +1 -1
- package/dist/src/ui/themes/builtin/dark/tokyonight-dark.d.ts +7 -0
- package/dist/src/ui/themes/builtin/dark/tokyonight-dark.js +147 -0
- package/dist/src/ui/themes/builtin/dark/tokyonight-dark.js.map +1 -0
- package/dist/src/ui/themes/theme-manager.js +2 -0
- package/dist/src/ui/themes/theme-manager.js.map +1 -1
- package/dist/src/ui/themes/theme.js +1 -1
- package/dist/src/ui/themes/theme.js.map +1 -1
- package/dist/src/ui/types.d.ts +10 -2
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/CodeColorizer.d.ts +1 -0
- package/dist/src/ui/utils/CodeColorizer.js +17 -18
- package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
- package/dist/src/ui/utils/ConsolePatcher.d.ts +1 -0
- package/dist/src/ui/utils/ConsolePatcher.js +12 -5
- package/dist/src/ui/utils/ConsolePatcher.js.map +1 -1
- package/dist/src/ui/utils/ConsolePatcher.test.d.ts +6 -0
- package/dist/src/ui/utils/ConsolePatcher.test.js +199 -0
- package/dist/src/ui/utils/ConsolePatcher.test.js.map +1 -0
- package/dist/src/ui/utils/TableRenderer.js +3 -3
- package/dist/src/ui/utils/TableRenderer.js.map +1 -1
- package/dist/src/ui/utils/borderStyles.d.ts +2 -2
- package/dist/src/ui/utils/borderStyles.js +2 -2
- package/dist/src/ui/utils/borderStyles.js.map +1 -1
- package/dist/src/ui/utils/directoryUtils.js +1 -1
- package/dist/src/ui/utils/directoryUtils.js.map +1 -1
- package/dist/src/ui/utils/fileUtils.d.ts +10 -0
- package/dist/src/ui/utils/fileUtils.js +17 -0
- package/dist/src/ui/utils/fileUtils.js.map +1 -0
- package/dist/src/ui/utils/terminalCapabilityManager.d.ts +1 -0
- package/dist/src/ui/utils/terminalCapabilityManager.js +8 -0
- package/dist/src/ui/utils/terminalCapabilityManager.js.map +1 -1
- package/dist/src/ui/utils/terminalCapabilityManager.test.js +38 -0
- package/dist/src/ui/utils/terminalCapabilityManager.test.js.map +1 -1
- package/dist/src/ui/utils/toolLayoutUtils.d.ts +1 -1
- package/dist/src/ui/utils/toolLayoutUtils.js +1 -1
- package/dist/src/ui/utils/ui-sizing.test.js +1 -0
- package/dist/src/ui/utils/ui-sizing.test.js.map +1 -1
- package/dist/src/ui/utils/updateCheck.d.ts +1 -0
- package/dist/src/ui/utils/updateCheck.js.map +1 -1
- package/dist/src/utils/activityLogger.js +16 -0
- package/dist/src/utils/activityLogger.js.map +1 -1
- package/dist/src/utils/cleanup.js +12 -5
- package/dist/src/utils/cleanup.js.map +1 -1
- package/dist/src/utils/commands.js +15 -0
- package/dist/src/utils/commands.js.map +1 -1
- package/dist/src/utils/commands.test.js +79 -0
- package/dist/src/utils/commands.test.js.map +1 -1
- package/dist/src/utils/envVarResolver.d.ts +5 -2
- package/dist/src/utils/envVarResolver.js +15 -6
- package/dist/src/utils/envVarResolver.js.map +1 -1
- package/dist/src/utils/envVarResolver.test.js +41 -24
- package/dist/src/utils/envVarResolver.test.js.map +1 -1
- package/dist/src/utils/errors.js +4 -4
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/events.d.ts +3 -1
- package/dist/src/utils/events.js +1 -0
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/gitUtils.js +4 -4
- package/dist/src/utils/gitUtils.js.map +1 -1
- package/dist/src/utils/handleAutoUpdate.js +10 -3
- package/dist/src/utils/handleAutoUpdate.js.map +1 -1
- package/dist/src/utils/handleAutoUpdate.test.js +8 -2
- package/dist/src/utils/handleAutoUpdate.test.js.map +1 -1
- package/dist/src/utils/installationInfo.js +1 -1
- package/dist/src/utils/installationInfo.js.map +1 -1
- package/dist/src/utils/jsonoutput.js +1 -1
- package/dist/src/utils/jsonoutput.js.map +1 -1
- package/dist/src/utils/sandboxUtils.js +1 -1
- package/dist/src/utils/sandboxUtils.js.map +1 -1
- package/dist/src/utils/sessionCleanup.js +7 -30
- package/dist/src/utils/sessionCleanup.js.map +1 -1
- package/dist/src/utils/sessionCleanup.test.js +3 -0
- package/dist/src/utils/sessionCleanup.test.js.map +1 -1
- package/dist/src/utils/sessionUtils.js +1 -0
- package/dist/src/utils/sessionUtils.js.map +1 -1
- package/dist/src/utils/sessionUtils.test.js +179 -3
- package/dist/src/utils/sessionUtils.test.js.map +1 -1
- package/dist/src/utils/sessions.js +1 -1
- package/dist/src/utils/sessions.js.map +1 -1
- package/dist/src/utils/skillUtils.js +3 -1
- package/dist/src/utils/skillUtils.js.map +1 -1
- package/dist/src/utils/skillUtils.test.js +4 -6
- package/dist/src/utils/skillUtils.test.js.map +1 -1
- package/dist/src/utils/terminalNotifications.js +2 -4
- package/dist/src/utils/terminalNotifications.js.map +1 -1
- package/dist/src/utils/terminalNotifications.test.js +5 -3
- package/dist/src/utils/terminalNotifications.test.js.map +1 -1
- package/dist/src/utils/userStartupWarnings.js +2 -2
- package/dist/src/utils/userStartupWarnings.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/dist/src/ui/commands/shellsCommand.js.map +0 -1
- package/dist/src/ui/commands/shellsCommand.test.js +0 -29
- package/dist/src/ui/commands/shellsCommand.test.js.map +0 -1
- package/dist/src/ui/components/BackgroundShellDisplay.d.ts +0 -16
- package/dist/src/ui/components/BackgroundShellDisplay.js.map +0 -1
- package/dist/src/ui/components/BackgroundShellDisplay.test.js.map +0 -1
- package/dist/src/ui/hooks/shellCommandProcessor.d.ts +0 -28
- package/dist/src/ui/hooks/shellCommandProcessor.js.map +0 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +0 -1
- package/dist/src/ui/hooks/useBackgroundShellManager.d.ts +0 -22
- package/dist/src/ui/hooks/useBackgroundShellManager.js +0 -58
- package/dist/src/ui/hooks/useBackgroundShellManager.js.map +0 -1
- package/dist/src/ui/hooks/useBackgroundShellManager.test.js.map +0 -1
- /package/dist/src/{ui/commands/shellsCommand.test.d.ts → nonInteractiveCliAgentSession.test.d.ts} +0 -0
- /package/dist/src/ui/{components/BackgroundShellDisplay.test.d.ts → commands/tasksCommand.test.d.ts} +0 -0
- /package/dist/src/ui/{hooks/shellCommandProcessor.test.d.ts → components/BackgroundTaskDisplay.test.d.ts} +0 -0
- /package/dist/src/ui/hooks/{useBackgroundShellManager.test.d.ts → useBackgroundTaskManager.test.d.ts} +0 -0
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* @license
|
|
4
4
|
* Copyright 2025 Google LLC
|
|
5
5
|
* SPDX-License-Identifier: Apache-2.0
|
|
6
6
|
*/
|
|
7
|
-
import { renderWithProviders } from '../../test-utils/render.js';
|
|
7
|
+
import { renderWithProviders, cleanup } from '../../test-utils/render.js';
|
|
8
8
|
import { createMockSettings } from '../../test-utils/settings.js';
|
|
9
9
|
import { makeFakeConfig } from '@google/gemini-cli-core';
|
|
10
10
|
import { waitFor } from '../../test-utils/async.js';
|
|
11
|
-
import { act, useState } from 'react';
|
|
11
|
+
import { act, useState, useMemo } from 'react';
|
|
12
12
|
import { InputPrompt, tryTogglePasteExpansion, } from './InputPrompt.js';
|
|
13
|
+
import { InputContext } from '../contexts/InputContext.js';
|
|
13
14
|
import { calculateTransformationsForLine, calculateTransformedLine, } from './shared/text-buffer.js';
|
|
14
|
-
import { ApprovalMode, debugLogger, } from '@google/gemini-cli-core';
|
|
15
|
+
import { ApprovalMode, debugLogger, coreEvents, } from '@google/gemini-cli-core';
|
|
15
16
|
import * as path from 'node:path';
|
|
16
17
|
import { CommandKind, } from '../commands/types.js';
|
|
17
18
|
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
|
@@ -31,7 +32,9 @@ import { terminalCapabilityManager } from '../utils/terminalCapabilityManager.js
|
|
|
31
32
|
import { isLowColorDepth } from '../utils/terminalUtils.js';
|
|
32
33
|
import { cpLen } from '../utils/textUtils.js';
|
|
33
34
|
import { defaultKeyMatchers, Command } from '../key/keyMatchers.js';
|
|
35
|
+
import { useKeypress } from '../hooks/useKeypress.js';
|
|
34
36
|
import { appEvents, AppEvent, TransientMessageType, } from '../../utils/events.js';
|
|
37
|
+
import '../../test-utils/customMatchers.js';
|
|
35
38
|
vi.mock('../hooks/useShellHistory.js');
|
|
36
39
|
vi.mock('../hooks/useCommandCompletion.js');
|
|
37
40
|
vi.mock('../hooks/useInputHistory.js');
|
|
@@ -52,6 +55,8 @@ vi.mock('ink', async (importOriginal) => {
|
|
|
52
55
|
});
|
|
53
56
|
afterEach(() => {
|
|
54
57
|
vi.restoreAllMocks();
|
|
58
|
+
vi.useRealTimers();
|
|
59
|
+
cleanup();
|
|
55
60
|
});
|
|
56
61
|
const mockSlashCommands = [
|
|
57
62
|
{
|
|
@@ -112,6 +117,26 @@ const mockSlashCommands = [
|
|
|
112
117
|
action: vi.fn(),
|
|
113
118
|
},
|
|
114
119
|
];
|
|
120
|
+
const TestInputPrompt = (props) => {
|
|
121
|
+
const contextValue = useMemo(() => ({
|
|
122
|
+
buffer: props.buffer,
|
|
123
|
+
userMessages: props.userMessages,
|
|
124
|
+
shellModeActive: props.shellModeActive,
|
|
125
|
+
copyModeEnabled: props.copyModeEnabled,
|
|
126
|
+
showEscapePrompt: props.showEscapePrompt || false,
|
|
127
|
+
inputWidth: props.inputWidth,
|
|
128
|
+
suggestionsWidth: props.suggestionsWidth,
|
|
129
|
+
}), [
|
|
130
|
+
props.buffer,
|
|
131
|
+
props.userMessages,
|
|
132
|
+
props.shellModeActive,
|
|
133
|
+
props.copyModeEnabled,
|
|
134
|
+
props.showEscapePrompt,
|
|
135
|
+
props.inputWidth,
|
|
136
|
+
props.suggestionsWidth,
|
|
137
|
+
]);
|
|
138
|
+
return (_jsx(InputContext.Provider, { value: contextValue, children: _jsx(InputPrompt, { ...props }) }));
|
|
139
|
+
};
|
|
115
140
|
describe('InputPrompt', () => {
|
|
116
141
|
let props;
|
|
117
142
|
let mockShellHistory;
|
|
@@ -120,6 +145,15 @@ describe('InputPrompt', () => {
|
|
|
120
145
|
let mockReverseSearchCompletion;
|
|
121
146
|
let mockBuffer;
|
|
122
147
|
let mockCommandContext;
|
|
148
|
+
const GlobalEscapeHandler = ({ onEscape }) => {
|
|
149
|
+
useKeypress((key) => {
|
|
150
|
+
if (key.name !== 'escape')
|
|
151
|
+
return false;
|
|
152
|
+
onEscape();
|
|
153
|
+
return true;
|
|
154
|
+
}, { isActive: true, priority: false });
|
|
155
|
+
return null;
|
|
156
|
+
};
|
|
123
157
|
const mockedUseShellHistory = vi.mocked(useShellHistory);
|
|
124
158
|
const mockedUseCommandCompletion = vi.mocked(useCommandCompletion);
|
|
125
159
|
const mockedUseInputHistory = vi.mocked(useInputHistory);
|
|
@@ -134,9 +168,11 @@ describe('InputPrompt', () => {
|
|
|
134
168
|
setCleanUiDetailsVisible: mockSetCleanUiDetailsVisible,
|
|
135
169
|
toggleCleanUiDetailsVisible: mockToggleCleanUiDetailsVisible,
|
|
136
170
|
revealCleanUiDetailsTemporarily: mockRevealCleanUiDetailsTemporarily,
|
|
171
|
+
addMessage: vi.fn(),
|
|
137
172
|
};
|
|
138
173
|
beforeEach(() => {
|
|
139
174
|
vi.resetAllMocks();
|
|
175
|
+
coreEvents.removeAllListeners();
|
|
140
176
|
vi.spyOn(terminalCapabilityManager, 'isKittyProtocolEnabled').mockReturnValue(true);
|
|
141
177
|
mockCommandContext = createMockCommandContext();
|
|
142
178
|
mockBuffer = {
|
|
@@ -145,7 +181,7 @@ describe('InputPrompt', () => {
|
|
|
145
181
|
lines: [''],
|
|
146
182
|
setText: vi.fn((newText, cursorPosition) => {
|
|
147
183
|
mockBuffer.text = newText;
|
|
148
|
-
mockBuffer.lines =
|
|
184
|
+
mockBuffer.lines = newText.split('\n');
|
|
149
185
|
let col = 0;
|
|
150
186
|
if (typeof cursorPosition === 'number') {
|
|
151
187
|
col = cursorPosition;
|
|
@@ -157,16 +193,25 @@ describe('InputPrompt', () => {
|
|
|
157
193
|
col = newText.length;
|
|
158
194
|
}
|
|
159
195
|
mockBuffer.cursor = [0, col];
|
|
160
|
-
mockBuffer.
|
|
161
|
-
mockBuffer.
|
|
162
|
-
mockBuffer.visualToLogicalMap =
|
|
196
|
+
mockBuffer.allVisualLines = newText.split('\n');
|
|
197
|
+
mockBuffer.viewportVisualLines = newText.split('\n');
|
|
198
|
+
mockBuffer.visualToLogicalMap = newText
|
|
199
|
+
.split('\n')
|
|
200
|
+
.map((_, i) => [i, 0]);
|
|
163
201
|
mockBuffer.visualCursor = [0, col];
|
|
202
|
+
mockBuffer.visualScrollRow = 0;
|
|
203
|
+
mockBuffer.viewportHeight = 10;
|
|
204
|
+
mockBuffer.visualToTransformedMap = newText
|
|
205
|
+
.split('\n')
|
|
206
|
+
.map((_, i) => i);
|
|
207
|
+
mockBuffer.transformationsByLine = newText.split('\n').map(() => []);
|
|
164
208
|
}),
|
|
165
209
|
replaceRangeByOffset: vi.fn(),
|
|
166
210
|
viewportVisualLines: [''],
|
|
167
211
|
allVisualLines: [''],
|
|
168
212
|
visualCursor: [0, 0],
|
|
169
213
|
visualScrollRow: 0,
|
|
214
|
+
viewportHeight: 10,
|
|
170
215
|
handleInput: vi.fn((key) => {
|
|
171
216
|
if (defaultKeyMatchers[Command.CLEAR_INPUT](key)) {
|
|
172
217
|
if (mockBuffer.text.length > 0) {
|
|
@@ -280,6 +325,7 @@ describe('InputPrompt', () => {
|
|
|
280
325
|
});
|
|
281
326
|
vi.mocked(clipboardy.read).mockResolvedValue('');
|
|
282
327
|
props = {
|
|
328
|
+
onQueueMessage: vi.fn(),
|
|
283
329
|
buffer: mockBuffer,
|
|
284
330
|
onSubmit: vi.fn(),
|
|
285
331
|
userMessages: [],
|
|
@@ -289,6 +335,7 @@ describe('InputPrompt', () => {
|
|
|
289
335
|
getTargetDir: () => path.join('test', 'project', 'src'),
|
|
290
336
|
getVimMode: () => false,
|
|
291
337
|
getUseBackgroundColor: () => true,
|
|
338
|
+
getUseTerminalBuffer: () => false,
|
|
292
339
|
getTerminalBackground: () => undefined,
|
|
293
340
|
getWorkspaceContext: () => ({
|
|
294
341
|
getDirectories: () => ['/test/project/src'],
|
|
@@ -309,7 +356,7 @@ describe('InputPrompt', () => {
|
|
|
309
356
|
});
|
|
310
357
|
it('should call shellHistory.getPreviousCommand on up arrow in shell mode', async () => {
|
|
311
358
|
props.shellModeActive = true;
|
|
312
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
359
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
313
360
|
uiActions,
|
|
314
361
|
});
|
|
315
362
|
await act(async () => {
|
|
@@ -320,7 +367,7 @@ describe('InputPrompt', () => {
|
|
|
320
367
|
});
|
|
321
368
|
it('should call shellHistory.getNextCommand on down arrow in shell mode', async () => {
|
|
322
369
|
props.shellModeActive = true;
|
|
323
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
370
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
324
371
|
uiActions,
|
|
325
372
|
});
|
|
326
373
|
await act(async () => {
|
|
@@ -332,7 +379,7 @@ describe('InputPrompt', () => {
|
|
|
332
379
|
it('should set the buffer text when a shell history command is retrieved', async () => {
|
|
333
380
|
props.shellModeActive = true;
|
|
334
381
|
vi.mocked(mockShellHistory.getPreviousCommand).mockReturnValue('previous command');
|
|
335
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
382
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
336
383
|
uiActions,
|
|
337
384
|
});
|
|
338
385
|
await act(async () => {
|
|
@@ -347,7 +394,7 @@ describe('InputPrompt', () => {
|
|
|
347
394
|
it('should call shellHistory.addCommandToHistory on submit in shell mode', async () => {
|
|
348
395
|
props.shellModeActive = true;
|
|
349
396
|
props.buffer.setText('ls -l');
|
|
350
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
397
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
351
398
|
uiActions,
|
|
352
399
|
});
|
|
353
400
|
await act(async () => {
|
|
@@ -371,7 +418,7 @@ describe('InputPrompt', () => {
|
|
|
371
418
|
],
|
|
372
419
|
activeSuggestionIndex: 0,
|
|
373
420
|
});
|
|
374
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
421
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
375
422
|
uiActions,
|
|
376
423
|
});
|
|
377
424
|
// Press Enter without navigating — should dismiss suggestions and fall
|
|
@@ -398,7 +445,7 @@ describe('InputPrompt', () => {
|
|
|
398
445
|
],
|
|
399
446
|
activeSuggestionIndex: 1,
|
|
400
447
|
});
|
|
401
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
448
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
402
449
|
uiActions,
|
|
403
450
|
});
|
|
404
451
|
// Press ArrowDown to navigate, then Enter to accept
|
|
@@ -417,7 +464,7 @@ describe('InputPrompt', () => {
|
|
|
417
464
|
});
|
|
418
465
|
it('should NOT call shell history methods when not in shell mode', async () => {
|
|
419
466
|
props.buffer.setText('some text');
|
|
420
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
467
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
421
468
|
uiActions,
|
|
422
469
|
});
|
|
423
470
|
await act(async () => {
|
|
@@ -442,7 +489,7 @@ describe('InputPrompt', () => {
|
|
|
442
489
|
mockBuffer.allVisualLines = ['line 1', 'line 2'];
|
|
443
490
|
mockBuffer.visualCursor = [0, 5]; // First line, not at start
|
|
444
491
|
mockBuffer.visualScrollRow = 0;
|
|
445
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
492
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
446
493
|
uiActions,
|
|
447
494
|
});
|
|
448
495
|
await act(async () => {
|
|
@@ -458,7 +505,7 @@ describe('InputPrompt', () => {
|
|
|
458
505
|
mockBuffer.allVisualLines = ['line 1', 'line 2'];
|
|
459
506
|
mockBuffer.visualCursor = [0, 0]; // First line, at start
|
|
460
507
|
mockBuffer.visualScrollRow = 0;
|
|
461
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
508
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
462
509
|
uiActions,
|
|
463
510
|
});
|
|
464
511
|
await act(async () => {
|
|
@@ -474,7 +521,7 @@ describe('InputPrompt', () => {
|
|
|
474
521
|
mockBuffer.allVisualLines = ['line 1', 'line 2'];
|
|
475
522
|
mockBuffer.visualCursor = [1, 0]; // Last line, not at end
|
|
476
523
|
mockBuffer.visualScrollRow = 0;
|
|
477
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
524
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
478
525
|
uiActions,
|
|
479
526
|
});
|
|
480
527
|
await act(async () => {
|
|
@@ -490,7 +537,7 @@ describe('InputPrompt', () => {
|
|
|
490
537
|
mockBuffer.allVisualLines = ['line 1', 'line 2'];
|
|
491
538
|
mockBuffer.visualCursor = [1, 6]; // Last line, at end ("line 2" is length 6)
|
|
492
539
|
mockBuffer.visualScrollRow = 0;
|
|
493
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
540
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
494
541
|
uiActions,
|
|
495
542
|
});
|
|
496
543
|
await act(async () => {
|
|
@@ -513,7 +560,7 @@ describe('InputPrompt', () => {
|
|
|
513
560
|
],
|
|
514
561
|
});
|
|
515
562
|
props.buffer.setText('/mem');
|
|
516
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
563
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
517
564
|
uiActions,
|
|
518
565
|
});
|
|
519
566
|
// Test up arrow
|
|
@@ -538,7 +585,7 @@ describe('InputPrompt', () => {
|
|
|
538
585
|
],
|
|
539
586
|
});
|
|
540
587
|
props.buffer.setText('/mem');
|
|
541
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
588
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
542
589
|
uiActions,
|
|
543
590
|
});
|
|
544
591
|
// Test down arrow
|
|
@@ -559,7 +606,7 @@ describe('InputPrompt', () => {
|
|
|
559
606
|
showSuggestions: false,
|
|
560
607
|
});
|
|
561
608
|
props.buffer.setText('some text');
|
|
562
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
609
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
563
610
|
uiActions,
|
|
564
611
|
});
|
|
565
612
|
await act(async () => {
|
|
@@ -584,7 +631,7 @@ describe('InputPrompt', () => {
|
|
|
584
631
|
});
|
|
585
632
|
it('should clear the buffer and reset completion on Ctrl+C', async () => {
|
|
586
633
|
mockBuffer.text = 'some text';
|
|
587
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
634
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
588
635
|
uiActions,
|
|
589
636
|
});
|
|
590
637
|
await act(async () => {
|
|
@@ -605,7 +652,7 @@ describe('InputPrompt', () => {
|
|
|
605
652
|
it('should handle Ctrl+V when clipboard has an image', async () => {
|
|
606
653
|
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(true);
|
|
607
654
|
vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue('/test/.cell-cli-clipboard/clipboard-123.png');
|
|
608
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
655
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
609
656
|
// Send Ctrl+V
|
|
610
657
|
await act(async () => {
|
|
611
658
|
stdin.write('\x16'); // Ctrl+V
|
|
@@ -620,7 +667,7 @@ describe('InputPrompt', () => {
|
|
|
620
667
|
});
|
|
621
668
|
it('should not insert anything when clipboard has no image', async () => {
|
|
622
669
|
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
|
|
623
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
670
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
624
671
|
await act(async () => {
|
|
625
672
|
stdin.write('\x16'); // Ctrl+V
|
|
626
673
|
});
|
|
@@ -634,7 +681,7 @@ describe('InputPrompt', () => {
|
|
|
634
681
|
it('should handle image save failure gracefully', async () => {
|
|
635
682
|
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(true);
|
|
636
683
|
vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue(null);
|
|
637
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
684
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
638
685
|
await act(async () => {
|
|
639
686
|
stdin.write('\x16'); // Ctrl+V
|
|
640
687
|
});
|
|
@@ -654,7 +701,7 @@ describe('InputPrompt', () => {
|
|
|
654
701
|
vi.mocked(mockBuffer.getOffset).mockReturnValue(5);
|
|
655
702
|
mockBuffer.lines = ['Hello world'];
|
|
656
703
|
mockBuffer.replaceRangeByOffset = vi.fn();
|
|
657
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
704
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
658
705
|
await act(async () => {
|
|
659
706
|
stdin.write('\x16'); // Ctrl+V
|
|
660
707
|
});
|
|
@@ -675,7 +722,7 @@ describe('InputPrompt', () => {
|
|
|
675
722
|
.spyOn(debugLogger, 'error')
|
|
676
723
|
.mockImplementation(() => { });
|
|
677
724
|
vi.mocked(clipboardUtils.clipboardHasImage).mockRejectedValue(new Error('Clipboard error'));
|
|
678
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
725
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
679
726
|
await act(async () => {
|
|
680
727
|
stdin.write('\x16'); // Ctrl+V
|
|
681
728
|
});
|
|
@@ -692,7 +739,7 @@ describe('InputPrompt', () => {
|
|
|
692
739
|
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
|
|
693
740
|
vi.mocked(clipboardy.read).mockResolvedValue('pasted text');
|
|
694
741
|
vi.mocked(mockBuffer.replaceRangeByOffset).mockClear();
|
|
695
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
742
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
696
743
|
await act(async () => {
|
|
697
744
|
stdin.write('\x16'); // Ctrl+V
|
|
698
745
|
});
|
|
@@ -707,7 +754,7 @@ describe('InputPrompt', () => {
|
|
|
707
754
|
const settings = createMockSettings({
|
|
708
755
|
experimental: { useOSC52Paste: true },
|
|
709
756
|
});
|
|
710
|
-
const { stdout, stdin, unmount } = await renderWithProviders(_jsx(
|
|
757
|
+
const { stdout, stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { settings });
|
|
711
758
|
const writeSpy = vi.spyOn(stdout, 'write');
|
|
712
759
|
await act(async () => {
|
|
713
760
|
stdin.write('\x16'); // Ctrl+V
|
|
@@ -759,7 +806,7 @@ describe('InputPrompt', () => {
|
|
|
759
806
|
activeSuggestionIndex: activeIndex,
|
|
760
807
|
});
|
|
761
808
|
props.buffer.setText(bufferText);
|
|
762
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
809
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
763
810
|
uiActions,
|
|
764
811
|
});
|
|
765
812
|
await act(async () => stdin.write('\t'));
|
|
@@ -774,7 +821,7 @@ describe('InputPrompt', () => {
|
|
|
774
821
|
activeSuggestionIndex: 0,
|
|
775
822
|
});
|
|
776
823
|
props.buffer.setText('/mem');
|
|
777
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
824
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
778
825
|
uiActions,
|
|
779
826
|
});
|
|
780
827
|
await act(async () => {
|
|
@@ -803,7 +850,7 @@ describe('InputPrompt', () => {
|
|
|
803
850
|
activeSuggestionIndex: 0,
|
|
804
851
|
});
|
|
805
852
|
props.buffer.setText('/?');
|
|
806
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
853
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
807
854
|
uiActions,
|
|
808
855
|
});
|
|
809
856
|
await act(async () => {
|
|
@@ -812,9 +859,55 @@ describe('InputPrompt', () => {
|
|
|
812
859
|
await waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0));
|
|
813
860
|
unmount();
|
|
814
861
|
});
|
|
862
|
+
it('queues a message when Tab is pressed during generation', async () => {
|
|
863
|
+
props.buffer.setText('A new prompt');
|
|
864
|
+
props.streamingState = StreamingState.Responding;
|
|
865
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
866
|
+
uiActions,
|
|
867
|
+
});
|
|
868
|
+
await act(async () => {
|
|
869
|
+
stdin.write('\t');
|
|
870
|
+
});
|
|
871
|
+
await waitFor(() => {
|
|
872
|
+
expect(props.onQueueMessage).toHaveBeenCalledWith('A new prompt');
|
|
873
|
+
expect(props.buffer.text).toBe('');
|
|
874
|
+
});
|
|
875
|
+
unmount();
|
|
876
|
+
});
|
|
877
|
+
it('shows an error when attempting to queue a slash command', async () => {
|
|
878
|
+
props.buffer.setText('/clear');
|
|
879
|
+
props.streamingState = StreamingState.Responding;
|
|
880
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
881
|
+
uiActions,
|
|
882
|
+
});
|
|
883
|
+
await act(async () => {
|
|
884
|
+
stdin.write('\t');
|
|
885
|
+
});
|
|
886
|
+
await waitFor(() => {
|
|
887
|
+
expect(props.setQueueErrorMessage).toHaveBeenCalledWith('Slash commands cannot be queued');
|
|
888
|
+
expect(props.onQueueMessage).not.toHaveBeenCalled();
|
|
889
|
+
});
|
|
890
|
+
unmount();
|
|
891
|
+
});
|
|
892
|
+
it('shows an error when attempting to queue a shell command', async () => {
|
|
893
|
+
props.shellModeActive = true;
|
|
894
|
+
props.buffer.setText('ls');
|
|
895
|
+
props.streamingState = StreamingState.Responding;
|
|
896
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
897
|
+
uiActions,
|
|
898
|
+
});
|
|
899
|
+
await act(async () => {
|
|
900
|
+
stdin.write('\t');
|
|
901
|
+
});
|
|
902
|
+
await waitFor(() => {
|
|
903
|
+
expect(props.setQueueErrorMessage).toHaveBeenCalledWith('Shell commands cannot be queued');
|
|
904
|
+
expect(props.onQueueMessage).not.toHaveBeenCalled();
|
|
905
|
+
});
|
|
906
|
+
unmount();
|
|
907
|
+
});
|
|
815
908
|
it('should not submit on Enter when the buffer is empty or only contains whitespace', async () => {
|
|
816
909
|
props.buffer.setText(' '); // Set buffer to whitespace
|
|
817
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
910
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
818
911
|
uiActions,
|
|
819
912
|
});
|
|
820
913
|
await act(async () => {
|
|
@@ -832,7 +925,7 @@ describe('InputPrompt', () => {
|
|
|
832
925
|
isPerfectMatch: true,
|
|
833
926
|
});
|
|
834
927
|
props.buffer.setText('/clear');
|
|
835
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
928
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
836
929
|
uiActions,
|
|
837
930
|
});
|
|
838
931
|
await act(async () => {
|
|
@@ -853,7 +946,7 @@ describe('InputPrompt', () => {
|
|
|
853
946
|
isPerfectMatch: true,
|
|
854
947
|
});
|
|
855
948
|
props.buffer.text = '/review';
|
|
856
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
949
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
857
950
|
uiActions,
|
|
858
951
|
});
|
|
859
952
|
await act(async () => {
|
|
@@ -876,7 +969,7 @@ describe('InputPrompt', () => {
|
|
|
876
969
|
isPerfectMatch: true, // /review is a perfect match
|
|
877
970
|
});
|
|
878
971
|
props.buffer.text = '/review';
|
|
879
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
972
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
880
973
|
uiActions,
|
|
881
974
|
});
|
|
882
975
|
await act(async () => {
|
|
@@ -897,7 +990,7 @@ describe('InputPrompt', () => {
|
|
|
897
990
|
isPerfectMatch: false, // Added explicit isPerfectMatch false
|
|
898
991
|
});
|
|
899
992
|
props.buffer.setText('/clear');
|
|
900
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
993
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
901
994
|
uiActions,
|
|
902
995
|
});
|
|
903
996
|
await act(async () => {
|
|
@@ -916,7 +1009,7 @@ describe('InputPrompt', () => {
|
|
|
916
1009
|
completionMode: CompletionMode.AT,
|
|
917
1010
|
});
|
|
918
1011
|
props.buffer.text = '@file.txt';
|
|
919
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1012
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
920
1013
|
uiActions,
|
|
921
1014
|
});
|
|
922
1015
|
await act(async () => {
|
|
@@ -938,7 +1031,7 @@ describe('InputPrompt', () => {
|
|
|
938
1031
|
completionMode: CompletionMode.AT,
|
|
939
1032
|
});
|
|
940
1033
|
props.buffer.text = '@file.txt';
|
|
941
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1034
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
942
1035
|
uiActions,
|
|
943
1036
|
});
|
|
944
1037
|
await act(async () => {
|
|
@@ -978,7 +1071,7 @@ describe('InputPrompt', () => {
|
|
|
978
1071
|
props.buffer.setText('/ab');
|
|
979
1072
|
props.buffer.lines = ['/ab'];
|
|
980
1073
|
props.buffer.cursor = [0, 3];
|
|
981
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1074
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
982
1075
|
uiActions,
|
|
983
1076
|
});
|
|
984
1077
|
await act(async () => {
|
|
@@ -1012,7 +1105,7 @@ describe('InputPrompt', () => {
|
|
|
1012
1105
|
props.buffer.setText('/sh');
|
|
1013
1106
|
props.buffer.lines = ['/sh'];
|
|
1014
1107
|
props.buffer.cursor = [0, 3];
|
|
1015
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1108
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1016
1109
|
uiActions,
|
|
1017
1110
|
});
|
|
1018
1111
|
await act(async () => {
|
|
@@ -1045,7 +1138,7 @@ describe('InputPrompt', () => {
|
|
|
1045
1138
|
props.buffer.setText('/ab');
|
|
1046
1139
|
props.buffer.lines = ['/ab'];
|
|
1047
1140
|
props.buffer.cursor = [0, 3];
|
|
1048
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1141
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1049
1142
|
uiActions,
|
|
1050
1143
|
});
|
|
1051
1144
|
await act(async () => {
|
|
@@ -1070,7 +1163,7 @@ describe('InputPrompt', () => {
|
|
|
1070
1163
|
props.buffer.setText('/ab');
|
|
1071
1164
|
props.buffer.lines = ['/ab'];
|
|
1072
1165
|
props.buffer.cursor = [0, 3];
|
|
1073
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1166
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1074
1167
|
uiActions,
|
|
1075
1168
|
});
|
|
1076
1169
|
await act(async () => {
|
|
@@ -1101,7 +1194,7 @@ describe('InputPrompt', () => {
|
|
|
1101
1194
|
props.buffer.setText('/find');
|
|
1102
1195
|
props.buffer.lines = ['/find'];
|
|
1103
1196
|
props.buffer.cursor = [0, 5];
|
|
1104
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1197
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1105
1198
|
uiActions,
|
|
1106
1199
|
});
|
|
1107
1200
|
await act(async () => {
|
|
@@ -1143,7 +1236,7 @@ describe('InputPrompt', () => {
|
|
|
1143
1236
|
props.buffer.setText('/mcp auth ');
|
|
1144
1237
|
props.buffer.lines = ['/mcp auth '];
|
|
1145
1238
|
props.buffer.cursor = [0, 10];
|
|
1146
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1239
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1147
1240
|
uiActions,
|
|
1148
1241
|
});
|
|
1149
1242
|
await act(async () => {
|
|
@@ -1190,7 +1283,7 @@ describe('InputPrompt', () => {
|
|
|
1190
1283
|
props.buffer.setText('/extensions enable ');
|
|
1191
1284
|
props.buffer.lines = ['/extensions enable '];
|
|
1192
1285
|
props.buffer.cursor = [0, 19];
|
|
1193
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1286
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1194
1287
|
uiActions,
|
|
1195
1288
|
});
|
|
1196
1289
|
await act(async () => {
|
|
@@ -1232,7 +1325,7 @@ describe('InputPrompt', () => {
|
|
|
1232
1325
|
props.buffer.setText('/chat resu');
|
|
1233
1326
|
props.buffer.lines = ['/chat resu'];
|
|
1234
1327
|
props.buffer.cursor = [0, 10];
|
|
1235
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1328
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1236
1329
|
uiActions,
|
|
1237
1330
|
});
|
|
1238
1331
|
await act(async () => {
|
|
@@ -1253,7 +1346,7 @@ describe('InputPrompt', () => {
|
|
|
1253
1346
|
activeSuggestionIndex: 0,
|
|
1254
1347
|
});
|
|
1255
1348
|
props.buffer.setText('@src/components/');
|
|
1256
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1349
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1257
1350
|
uiActions,
|
|
1258
1351
|
});
|
|
1259
1352
|
await act(async () => {
|
|
@@ -1268,7 +1361,7 @@ describe('InputPrompt', () => {
|
|
|
1268
1361
|
mockBuffer.text = 'first line\\';
|
|
1269
1362
|
mockBuffer.cursor = [0, 11];
|
|
1270
1363
|
mockBuffer.lines = ['first line\\'];
|
|
1271
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1364
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1272
1365
|
uiActions,
|
|
1273
1366
|
});
|
|
1274
1367
|
await act(async () => {
|
|
@@ -1285,7 +1378,7 @@ describe('InputPrompt', () => {
|
|
|
1285
1378
|
await act(async () => {
|
|
1286
1379
|
props.buffer.setText('some text to clear');
|
|
1287
1380
|
});
|
|
1288
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1381
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1289
1382
|
uiActions,
|
|
1290
1383
|
});
|
|
1291
1384
|
await act(async () => {
|
|
@@ -1300,7 +1393,7 @@ describe('InputPrompt', () => {
|
|
|
1300
1393
|
});
|
|
1301
1394
|
it('should render correctly in plan mode', async () => {
|
|
1302
1395
|
props.approvalMode = ApprovalMode.PLAN;
|
|
1303
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
1396
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1304
1397
|
await waitFor(() => {
|
|
1305
1398
|
const frame = stdout.lastFrameRaw();
|
|
1306
1399
|
// In plan mode it uses '>' but with success color.
|
|
@@ -1313,7 +1406,7 @@ describe('InputPrompt', () => {
|
|
|
1313
1406
|
});
|
|
1314
1407
|
it('should NOT clear the buffer on Ctrl+C if it is empty', async () => {
|
|
1315
1408
|
props.buffer.text = '';
|
|
1316
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1409
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1317
1410
|
uiActions,
|
|
1318
1411
|
});
|
|
1319
1412
|
await act(async () => {
|
|
@@ -1325,7 +1418,7 @@ describe('InputPrompt', () => {
|
|
|
1325
1418
|
unmount();
|
|
1326
1419
|
});
|
|
1327
1420
|
it('should call setBannerVisible(false) when clear screen key is pressed', async () => {
|
|
1328
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1421
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1329
1422
|
uiActions,
|
|
1330
1423
|
});
|
|
1331
1424
|
await act(async () => {
|
|
@@ -1344,7 +1437,7 @@ describe('InputPrompt', () => {
|
|
|
1344
1437
|
vi.restoreAllMocks();
|
|
1345
1438
|
});
|
|
1346
1439
|
it('should render with background color by default', async () => {
|
|
1347
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
1440
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1348
1441
|
await waitFor(() => {
|
|
1349
1442
|
const frame = stdout.lastFrameRaw();
|
|
1350
1443
|
expect(frame).toContain('▀');
|
|
@@ -1361,7 +1454,7 @@ describe('InputPrompt', () => {
|
|
|
1361
1454
|
{ color: '#fff', name: '#fff' },
|
|
1362
1455
|
])('should render with safe grey background but NO side borders in 8-bit mode when background is $name', async ({ color }) => {
|
|
1363
1456
|
vi.mocked(isLowColorDepth).mockReturnValue(true);
|
|
1364
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
1457
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1365
1458
|
uiState: {
|
|
1366
1459
|
terminalBackgroundColor: color,
|
|
1367
1460
|
},
|
|
@@ -1385,7 +1478,7 @@ describe('InputPrompt', () => {
|
|
|
1385
1478
|
});
|
|
1386
1479
|
it('should NOT render with background color but SHOULD render horizontal lines when color depth is < 24 and background is NOT black', async () => {
|
|
1387
1480
|
vi.mocked(isLowColorDepth).mockReturnValue(true);
|
|
1388
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
1481
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1389
1482
|
uiState: {
|
|
1390
1483
|
terminalBackgroundColor: '#333333',
|
|
1391
1484
|
},
|
|
@@ -1403,7 +1496,7 @@ describe('InputPrompt', () => {
|
|
|
1403
1496
|
});
|
|
1404
1497
|
it('should handle 4-bit color mode (16 colors) as low color depth', async () => {
|
|
1405
1498
|
vi.mocked(isLowColorDepth).mockReturnValue(true);
|
|
1406
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
1499
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1407
1500
|
uiState: {
|
|
1408
1501
|
terminalBackgroundColor: 'black',
|
|
1409
1502
|
},
|
|
@@ -1417,7 +1510,7 @@ describe('InputPrompt', () => {
|
|
|
1417
1510
|
});
|
|
1418
1511
|
it('should render horizontal lines (but NO background) in 8-bit mode when background is blue', async () => {
|
|
1419
1512
|
vi.mocked(isLowColorDepth).mockReturnValue(true);
|
|
1420
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
1513
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1421
1514
|
uiState: {
|
|
1422
1515
|
terminalBackgroundColor: 'blue',
|
|
1423
1516
|
},
|
|
@@ -1437,7 +1530,7 @@ describe('InputPrompt', () => {
|
|
|
1437
1530
|
});
|
|
1438
1531
|
it('should render with plain borders when useBackgroundColor is false', async () => {
|
|
1439
1532
|
props.config.getUseBackgroundColor = () => false;
|
|
1440
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
1533
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1441
1534
|
await waitFor(() => {
|
|
1442
1535
|
const frame = stdout.lastFrameRaw();
|
|
1443
1536
|
expect(frame).not.toContain('▀');
|
|
@@ -1539,7 +1632,7 @@ describe('InputPrompt', () => {
|
|
|
1539
1632
|
? [{ label: 'suggestion', value: 'suggestion' }]
|
|
1540
1633
|
: [],
|
|
1541
1634
|
});
|
|
1542
|
-
const { unmount } = await renderWithProviders(_jsx(
|
|
1635
|
+
const { unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
1543
1636
|
uiActions,
|
|
1544
1637
|
});
|
|
1545
1638
|
await waitFor(() => {
|
|
@@ -1576,7 +1669,7 @@ describe('InputPrompt', () => {
|
|
|
1576
1669
|
},
|
|
1577
1670
|
])('$name', async ({ vimHandled, expectBufferHandleInput }) => {
|
|
1578
1671
|
props.vimHandleInput = vi.fn().mockReturnValue(vimHandled);
|
|
1579
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1672
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1580
1673
|
await act(async () => stdin.write('i'));
|
|
1581
1674
|
await waitFor(() => {
|
|
1582
1675
|
expect(props.vimHandleInput).toHaveBeenCalled();
|
|
@@ -1593,7 +1686,7 @@ describe('InputPrompt', () => {
|
|
|
1593
1686
|
describe('unfocused paste', () => {
|
|
1594
1687
|
it('should handle bracketed paste when not focused', async () => {
|
|
1595
1688
|
props.focus = false;
|
|
1596
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1689
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1597
1690
|
await act(async () => {
|
|
1598
1691
|
stdin.write('\x1B[200~pasted text\x1B[201~');
|
|
1599
1692
|
});
|
|
@@ -1607,7 +1700,7 @@ describe('InputPrompt', () => {
|
|
|
1607
1700
|
});
|
|
1608
1701
|
it('should ignore regular keypresses when not focused', async () => {
|
|
1609
1702
|
props.focus = false;
|
|
1610
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1703
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1611
1704
|
await act(async () => {
|
|
1612
1705
|
stdin.write('a');
|
|
1613
1706
|
});
|
|
@@ -1672,10 +1765,11 @@ describe('InputPrompt', () => {
|
|
|
1672
1765
|
])('should display cursor correctly $name', async ({ text, visualCursor }) => {
|
|
1673
1766
|
mockBuffer.text = text;
|
|
1674
1767
|
mockBuffer.lines = [text];
|
|
1768
|
+
mockBuffer.allVisualLines = [text];
|
|
1675
1769
|
mockBuffer.viewportVisualLines = [text];
|
|
1676
1770
|
mockBuffer.visualCursor = visualCursor;
|
|
1677
1771
|
props.config.getUseBackgroundColor = () => false;
|
|
1678
|
-
const renderResult = await renderWithProviders(_jsx(
|
|
1772
|
+
const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1679
1773
|
await renderResult.waitUntilReady();
|
|
1680
1774
|
await expect(renderResult).toMatchSvgSnapshot();
|
|
1681
1775
|
renderResult.unmount();
|
|
@@ -1714,11 +1808,12 @@ describe('InputPrompt', () => {
|
|
|
1714
1808
|
])('should display cursor correctly $name in a multiline block', async ({ text, visualCursor, visualToLogicalMap }) => {
|
|
1715
1809
|
mockBuffer.text = text;
|
|
1716
1810
|
mockBuffer.lines = text.split('\n');
|
|
1811
|
+
mockBuffer.allVisualLines = text.split('\n');
|
|
1717
1812
|
mockBuffer.viewportVisualLines = text.split('\n');
|
|
1718
1813
|
mockBuffer.visualCursor = visualCursor;
|
|
1719
1814
|
mockBuffer.visualToLogicalMap = visualToLogicalMap;
|
|
1720
1815
|
props.config.getUseBackgroundColor = () => false;
|
|
1721
|
-
const renderResult = await renderWithProviders(_jsx(
|
|
1816
|
+
const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1722
1817
|
await renderResult.waitUntilReady();
|
|
1723
1818
|
await expect(renderResult).toMatchSvgSnapshot();
|
|
1724
1819
|
renderResult.unmount();
|
|
@@ -1727,6 +1822,7 @@ describe('InputPrompt', () => {
|
|
|
1727
1822
|
const text = 'first line\n\nthird line';
|
|
1728
1823
|
mockBuffer.text = text;
|
|
1729
1824
|
mockBuffer.lines = text.split('\n');
|
|
1825
|
+
mockBuffer.allVisualLines = text.split('\n');
|
|
1730
1826
|
mockBuffer.viewportVisualLines = text.split('\n');
|
|
1731
1827
|
mockBuffer.visualCursor = [1, 0]; // cursor on the blank line
|
|
1732
1828
|
mockBuffer.visualToLogicalMap = [
|
|
@@ -1735,18 +1831,102 @@ describe('InputPrompt', () => {
|
|
|
1735
1831
|
[2, 0],
|
|
1736
1832
|
];
|
|
1737
1833
|
props.config.getUseBackgroundColor = () => false;
|
|
1738
|
-
const renderResult = await renderWithProviders(_jsx(
|
|
1834
|
+
const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1739
1835
|
await renderResult.waitUntilReady();
|
|
1740
1836
|
await expect(renderResult).toMatchSvgSnapshot();
|
|
1741
1837
|
renderResult.unmount();
|
|
1742
1838
|
});
|
|
1743
1839
|
});
|
|
1744
1840
|
});
|
|
1841
|
+
describe('scrolling large inputs', () => {
|
|
1842
|
+
it('should correctly render scrolling down and up for large inputs', async () => {
|
|
1843
|
+
const lines = Array.from({ length: 50 }).map((_, i) => `testline ${i}`);
|
|
1844
|
+
// Since we need to test how the React component tree responds to TextBuffer state changes,
|
|
1845
|
+
// we must provide a fake TextBuffer implementation that triggers re-renders like the real one.
|
|
1846
|
+
const TestWrapper = () => {
|
|
1847
|
+
const [bufferState, setBufferState] = useState({
|
|
1848
|
+
text: lines.join('\n'),
|
|
1849
|
+
lines,
|
|
1850
|
+
allVisualLines: lines,
|
|
1851
|
+
viewportVisualLines: lines.slice(0, 10),
|
|
1852
|
+
visualToLogicalMap: lines.map((_, i) => [i, 0]),
|
|
1853
|
+
visualCursor: [0, 0],
|
|
1854
|
+
visualScrollRow: 0,
|
|
1855
|
+
viewportHeight: 10,
|
|
1856
|
+
});
|
|
1857
|
+
const fakeBuffer = {
|
|
1858
|
+
...mockBuffer,
|
|
1859
|
+
...bufferState,
|
|
1860
|
+
handleInput: vi.fn().mockImplementation((key) => {
|
|
1861
|
+
let newRow = bufferState.visualCursor[0];
|
|
1862
|
+
let newScroll = bufferState.visualScrollRow;
|
|
1863
|
+
if (key.name === 'down') {
|
|
1864
|
+
newRow = Math.min(49, newRow + 1);
|
|
1865
|
+
if (newRow >= newScroll + 10)
|
|
1866
|
+
newScroll++;
|
|
1867
|
+
}
|
|
1868
|
+
else if (key.name === 'up') {
|
|
1869
|
+
newRow = Math.max(0, newRow - 1);
|
|
1870
|
+
if (newRow < newScroll)
|
|
1871
|
+
newScroll--;
|
|
1872
|
+
}
|
|
1873
|
+
setBufferState({
|
|
1874
|
+
...bufferState,
|
|
1875
|
+
visualCursor: [newRow, 0],
|
|
1876
|
+
visualScrollRow: newScroll,
|
|
1877
|
+
viewportVisualLines: lines.slice(newScroll, newScroll + 10),
|
|
1878
|
+
});
|
|
1879
|
+
return true;
|
|
1880
|
+
}),
|
|
1881
|
+
};
|
|
1882
|
+
const inputState = {
|
|
1883
|
+
buffer: fakeBuffer,
|
|
1884
|
+
userMessages: [],
|
|
1885
|
+
shellModeActive: false,
|
|
1886
|
+
showEscapePrompt: false,
|
|
1887
|
+
copyModeEnabled: false,
|
|
1888
|
+
inputWidth: 80,
|
|
1889
|
+
suggestionsWidth: 80,
|
|
1890
|
+
};
|
|
1891
|
+
return (_jsx(InputContext.Provider, { value: inputState, children: _jsx(InputPrompt, { ...props }) }));
|
|
1892
|
+
};
|
|
1893
|
+
const { stdout, unmount, stdin } = await renderWithProviders(_jsx(TestWrapper, {}), {
|
|
1894
|
+
uiActions,
|
|
1895
|
+
});
|
|
1896
|
+
// Verify initial render
|
|
1897
|
+
await waitFor(() => {
|
|
1898
|
+
expect(stdout.lastFrame()).toContain('testline 0');
|
|
1899
|
+
expect(stdout.lastFrame()).not.toContain('testline 49');
|
|
1900
|
+
});
|
|
1901
|
+
// Move cursor to bottom
|
|
1902
|
+
for (let i = 0; i < 49; i++) {
|
|
1903
|
+
act(() => {
|
|
1904
|
+
stdin.write('\x1b[B'); // Arrow Down
|
|
1905
|
+
});
|
|
1906
|
+
}
|
|
1907
|
+
await waitFor(() => {
|
|
1908
|
+
expect(stdout.lastFrame()).toContain('testline 49');
|
|
1909
|
+
expect(stdout.lastFrame()).not.toContain('testline 0');
|
|
1910
|
+
});
|
|
1911
|
+
// Move cursor back to top
|
|
1912
|
+
for (let i = 0; i < 49; i++) {
|
|
1913
|
+
act(() => {
|
|
1914
|
+
stdin.write('\x1b[A'); // Arrow Up
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
await waitFor(() => {
|
|
1918
|
+
expect(stdout.lastFrame()).toContain('testline 0');
|
|
1919
|
+
expect(stdout.lastFrame()).not.toContain('testline 49');
|
|
1920
|
+
});
|
|
1921
|
+
unmount();
|
|
1922
|
+
});
|
|
1923
|
+
});
|
|
1745
1924
|
describe('multiline rendering', () => {
|
|
1746
1925
|
it('should correctly render multiline input including blank lines', async () => {
|
|
1747
1926
|
const text = 'hello\n\nworld';
|
|
1748
1927
|
mockBuffer.text = text;
|
|
1749
1928
|
mockBuffer.lines = text.split('\n');
|
|
1929
|
+
mockBuffer.allVisualLines = text.split('\n');
|
|
1750
1930
|
mockBuffer.viewportVisualLines = text.split('\n');
|
|
1751
1931
|
mockBuffer.allVisualLines = text.split('\n');
|
|
1752
1932
|
mockBuffer.visualCursor = [2, 5]; // cursor at the end of "world"
|
|
@@ -1757,7 +1937,7 @@ describe('InputPrompt', () => {
|
|
|
1757
1937
|
[2, 0],
|
|
1758
1938
|
];
|
|
1759
1939
|
props.config.getUseBackgroundColor = () => false;
|
|
1760
|
-
const renderResult = await renderWithProviders(_jsx(
|
|
1940
|
+
const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1761
1941
|
await renderResult.waitUntilReady();
|
|
1762
1942
|
await expect(renderResult).toMatchSvgSnapshot();
|
|
1763
1943
|
renderResult.unmount();
|
|
@@ -1778,7 +1958,7 @@ describe('InputPrompt', () => {
|
|
|
1778
1958
|
pastedText: 'This\r\nis\r\na\r\nmultiline\r\npaste.',
|
|
1779
1959
|
},
|
|
1780
1960
|
])('should handle multiline paste $description', async ({ pastedText }) => {
|
|
1781
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1961
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1782
1962
|
// Simulate a bracketed paste event from the terminal
|
|
1783
1963
|
await act(async () => {
|
|
1784
1964
|
stdin.write(`\x1b[200~${pastedText}\x1b[201~`);
|
|
@@ -1799,7 +1979,7 @@ describe('InputPrompt', () => {
|
|
|
1799
1979
|
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
|
|
1800
1980
|
const largeText = '1\n2\n3\n4\n5\n6';
|
|
1801
1981
|
vi.mocked(clipboardy.read).mockResolvedValue(largeText);
|
|
1802
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1982
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1803
1983
|
await act(async () => {
|
|
1804
1984
|
stdin.write('\x16'); // Ctrl+V
|
|
1805
1985
|
});
|
|
@@ -1812,7 +1992,7 @@ describe('InputPrompt', () => {
|
|
|
1812
1992
|
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
|
|
1813
1993
|
const largeText = 'a'.repeat(501);
|
|
1814
1994
|
vi.mocked(clipboardy.read).mockResolvedValue(largeText);
|
|
1815
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
1995
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1816
1996
|
await act(async () => {
|
|
1817
1997
|
stdin.write('\x16'); // Ctrl+V
|
|
1818
1998
|
});
|
|
@@ -1825,7 +2005,7 @@ describe('InputPrompt', () => {
|
|
|
1825
2005
|
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
|
|
1826
2006
|
const smallText = 'hello world';
|
|
1827
2007
|
vi.mocked(clipboardy.read).mockResolvedValue(smallText);
|
|
1828
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2008
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1829
2009
|
await act(async () => {
|
|
1830
2010
|
stdin.write('\x16'); // Ctrl+V
|
|
1831
2011
|
});
|
|
@@ -1840,7 +2020,7 @@ describe('InputPrompt', () => {
|
|
|
1840
2020
|
const id = '[Pasted Text: 6 lines]';
|
|
1841
2021
|
mockBuffer.text = `Check this: ${id}`;
|
|
1842
2022
|
mockBuffer.pastedContent = { [id]: largeText };
|
|
1843
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2023
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1844
2024
|
await act(async () => {
|
|
1845
2025
|
stdin.write('\r'); // Enter
|
|
1846
2026
|
});
|
|
@@ -1865,7 +2045,7 @@ describe('InputPrompt', () => {
|
|
|
1865
2045
|
it('should prevent auto-submission immediately after an unsafe paste', async () => {
|
|
1866
2046
|
// isTerminalPasteTrusted will be false due to beforeEach setup.
|
|
1867
2047
|
props.buffer.text = 'some command';
|
|
1868
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2048
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1869
2049
|
await act(async () => {
|
|
1870
2050
|
await vi.runAllTimersAsync();
|
|
1871
2051
|
});
|
|
@@ -1894,7 +2074,7 @@ describe('InputPrompt', () => {
|
|
|
1894
2074
|
completionMode: CompletionMode.AT,
|
|
1895
2075
|
});
|
|
1896
2076
|
props.buffer.text = '@file.txt';
|
|
1897
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2077
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1898
2078
|
// Simulate an unsafe paste of a perfect match
|
|
1899
2079
|
await act(async () => {
|
|
1900
2080
|
stdin.write(`\x1b[200~@file.txt\x1b[201~`);
|
|
@@ -1912,7 +2092,7 @@ describe('InputPrompt', () => {
|
|
|
1912
2092
|
it('should allow submission after unsafe paste protection timeout', async () => {
|
|
1913
2093
|
// isTerminalPasteTrusted will be false due to beforeEach setup.
|
|
1914
2094
|
props.buffer.text = 'pasted text';
|
|
1915
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2095
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1916
2096
|
await act(async () => {
|
|
1917
2097
|
await vi.runAllTimersAsync();
|
|
1918
2098
|
});
|
|
@@ -1949,7 +2129,7 @@ describe('InputPrompt', () => {
|
|
|
1949
2129
|
])('should allow immediate submission for a trusted paste ($name)', async ({ setup }) => {
|
|
1950
2130
|
setup();
|
|
1951
2131
|
props.buffer.text = 'pasted command';
|
|
1952
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2132
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1953
2133
|
await act(async () => {
|
|
1954
2134
|
await vi.runAllTimersAsync();
|
|
1955
2135
|
});
|
|
@@ -1974,7 +2154,7 @@ describe('InputPrompt', () => {
|
|
|
1974
2154
|
it('should not interfere with normal Enter key submission when no recent paste', async () => {
|
|
1975
2155
|
// Set up buffer with text before rendering to ensure submission works
|
|
1976
2156
|
props.buffer.text = 'normal command';
|
|
1977
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2157
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
1978
2158
|
await act(async () => {
|
|
1979
2159
|
await vi.runAllTimersAsync();
|
|
1980
2160
|
});
|
|
@@ -1997,7 +2177,7 @@ describe('InputPrompt', () => {
|
|
|
1997
2177
|
const onEscapePromptChange = vi.fn();
|
|
1998
2178
|
props.onEscapePromptChange = onEscapePromptChange;
|
|
1999
2179
|
props.buffer.setText('text to clear');
|
|
2000
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2180
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2001
2181
|
await act(async () => {
|
|
2002
2182
|
stdin.write('\x03');
|
|
2003
2183
|
vi.advanceTimersByTime(100);
|
|
@@ -2011,7 +2191,7 @@ describe('InputPrompt', () => {
|
|
|
2011
2191
|
props.onEscapePromptChange = onEscapePromptChange;
|
|
2012
2192
|
props.buffer.setText('');
|
|
2013
2193
|
vi.mocked(props.buffer.setText).mockClear();
|
|
2014
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2194
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
2015
2195
|
uiState: {
|
|
2016
2196
|
history: [{ id: 1, type: 'user', text: 'test' }],
|
|
2017
2197
|
},
|
|
@@ -2030,7 +2210,7 @@ describe('InputPrompt', () => {
|
|
|
2030
2210
|
props.onEscapePromptChange = onEscapePromptChange;
|
|
2031
2211
|
props.buffer.setText('some text');
|
|
2032
2212
|
vi.mocked(props.buffer.setText).mockClear();
|
|
2033
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2213
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2034
2214
|
await act(async () => {
|
|
2035
2215
|
stdin.write('\x1B\x1B');
|
|
2036
2216
|
vi.advanceTimersByTime(100);
|
|
@@ -2043,7 +2223,7 @@ describe('InputPrompt', () => {
|
|
|
2043
2223
|
const onEscapePromptChange = vi.fn();
|
|
2044
2224
|
props.onEscapePromptChange = onEscapePromptChange;
|
|
2045
2225
|
props.buffer.setText('some text');
|
|
2046
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2226
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2047
2227
|
await act(async () => {
|
|
2048
2228
|
stdin.write('\x1B');
|
|
2049
2229
|
await waitFor(() => {
|
|
@@ -2060,7 +2240,7 @@ describe('InputPrompt', () => {
|
|
|
2060
2240
|
});
|
|
2061
2241
|
it('should handle ESC in shell mode by disabling shell mode', async () => {
|
|
2062
2242
|
props.shellModeActive = true;
|
|
2063
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2243
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2064
2244
|
await act(async () => {
|
|
2065
2245
|
stdin.write('\x1B');
|
|
2066
2246
|
vi.advanceTimersByTime(100);
|
|
@@ -2068,13 +2248,43 @@ describe('InputPrompt', () => {
|
|
|
2068
2248
|
});
|
|
2069
2249
|
unmount();
|
|
2070
2250
|
});
|
|
2251
|
+
it('should not propagate ESC to global cancellation handler when shell mode is active (responding)', async () => {
|
|
2252
|
+
props.shellModeActive = true;
|
|
2253
|
+
props.streamingState = StreamingState.Responding;
|
|
2254
|
+
const onGlobalEscape = vi.fn();
|
|
2255
|
+
const { stdin, unmount } = await renderWithProviders(_jsxs(_Fragment, { children: [_jsx(GlobalEscapeHandler, { onEscape: onGlobalEscape }), _jsx(TestInputPrompt, { ...props })] }));
|
|
2256
|
+
await act(async () => {
|
|
2257
|
+
stdin.write('\x1B');
|
|
2258
|
+
vi.advanceTimersByTime(100);
|
|
2259
|
+
});
|
|
2260
|
+
await waitFor(() => {
|
|
2261
|
+
expect(props.setShellModeActive).toHaveBeenCalledWith(false);
|
|
2262
|
+
});
|
|
2263
|
+
expect(onGlobalEscape).not.toHaveBeenCalled();
|
|
2264
|
+
unmount();
|
|
2265
|
+
});
|
|
2266
|
+
it('should allow ESC to reach global cancellation handler when responding and no overlay is active', async () => {
|
|
2267
|
+
props.shellModeActive = false;
|
|
2268
|
+
props.streamingState = StreamingState.Responding;
|
|
2269
|
+
const onGlobalEscape = vi.fn();
|
|
2270
|
+
const { stdin, unmount } = await renderWithProviders(_jsxs(_Fragment, { children: [_jsx(GlobalEscapeHandler, { onEscape: onGlobalEscape }), _jsx(TestInputPrompt, { ...props })] }));
|
|
2271
|
+
await act(async () => {
|
|
2272
|
+
stdin.write('\x1B');
|
|
2273
|
+
vi.advanceTimersByTime(100);
|
|
2274
|
+
});
|
|
2275
|
+
await waitFor(() => {
|
|
2276
|
+
expect(onGlobalEscape).toHaveBeenCalledTimes(1);
|
|
2277
|
+
});
|
|
2278
|
+
expect(props.setShellModeActive).not.toHaveBeenCalled();
|
|
2279
|
+
unmount();
|
|
2280
|
+
});
|
|
2071
2281
|
it('should handle ESC when completion suggestions are showing', async () => {
|
|
2072
2282
|
mockedUseCommandCompletion.mockReturnValue({
|
|
2073
2283
|
...mockCommandCompletion,
|
|
2074
2284
|
showSuggestions: true,
|
|
2075
2285
|
suggestions: [{ label: 'suggestion', value: 'suggestion' }],
|
|
2076
2286
|
});
|
|
2077
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2287
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2078
2288
|
await act(async () => {
|
|
2079
2289
|
stdin.write('\x1B');
|
|
2080
2290
|
vi.advanceTimersByTime(100);
|
|
@@ -2085,7 +2295,7 @@ describe('InputPrompt', () => {
|
|
|
2085
2295
|
it('should not call onEscapePromptChange when not provided', async () => {
|
|
2086
2296
|
props.onEscapePromptChange = undefined;
|
|
2087
2297
|
props.buffer.setText('some text');
|
|
2088
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2298
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2089
2299
|
await act(async () => {
|
|
2090
2300
|
await vi.runAllTimersAsync();
|
|
2091
2301
|
});
|
|
@@ -2098,7 +2308,7 @@ describe('InputPrompt', () => {
|
|
|
2098
2308
|
unmount();
|
|
2099
2309
|
});
|
|
2100
2310
|
it('should not interfere with existing keyboard shortcuts', async () => {
|
|
2101
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2311
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2102
2312
|
await act(async () => {
|
|
2103
2313
|
stdin.write('\x0C');
|
|
2104
2314
|
});
|
|
@@ -2133,7 +2343,7 @@ describe('InputPrompt', () => {
|
|
|
2133
2343
|
showSuggestions: true,
|
|
2134
2344
|
activeSuggestionIndex: 0,
|
|
2135
2345
|
});
|
|
2136
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2346
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2137
2347
|
// Trigger reverse search with Ctrl+R
|
|
2138
2348
|
await act(async () => {
|
|
2139
2349
|
stdin.write('\x12');
|
|
@@ -2151,7 +2361,7 @@ describe('InputPrompt', () => {
|
|
|
2151
2361
|
{ name: 'standard', escapeSequence: '\x1B' },
|
|
2152
2362
|
{ name: 'kitty', escapeSequence: '\u001b[27u' },
|
|
2153
2363
|
])('resets reverse search state on Escape ($name)', async ({ escapeSequence }) => {
|
|
2154
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2364
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2155
2365
|
await act(async () => {
|
|
2156
2366
|
stdin.write('\x12');
|
|
2157
2367
|
});
|
|
@@ -2186,7 +2396,7 @@ describe('InputPrompt', () => {
|
|
|
2186
2396
|
activeSuggestionIndex: reverseSearchActive ? 0 : -1,
|
|
2187
2397
|
handleAutocomplete: mockHandleAutocomplete,
|
|
2188
2398
|
}));
|
|
2189
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2399
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2190
2400
|
// Enter reverse search mode with Ctrl+R
|
|
2191
2401
|
await act(async () => {
|
|
2192
2402
|
stdin.write('\x12');
|
|
@@ -2214,7 +2424,7 @@ describe('InputPrompt', () => {
|
|
|
2214
2424
|
activeSuggestionIndex: 0,
|
|
2215
2425
|
handleAutocomplete: mockHandleAutocomplete,
|
|
2216
2426
|
});
|
|
2217
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2427
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
2218
2428
|
uiActions,
|
|
2219
2429
|
});
|
|
2220
2430
|
await act(async () => {
|
|
@@ -2239,7 +2449,7 @@ describe('InputPrompt', () => {
|
|
|
2239
2449
|
showSuggestions: true,
|
|
2240
2450
|
activeSuggestionIndex: 0,
|
|
2241
2451
|
});
|
|
2242
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2452
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2243
2453
|
await act(async () => {
|
|
2244
2454
|
stdin.write('\x12');
|
|
2245
2455
|
});
|
|
@@ -2268,7 +2478,7 @@ describe('InputPrompt', () => {
|
|
|
2268
2478
|
: [],
|
|
2269
2479
|
showSuggestions: reverseSearchActiveFromInputPrompt,
|
|
2270
2480
|
}));
|
|
2271
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2481
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2272
2482
|
// reverse search with Ctrl+R
|
|
2273
2483
|
await act(async () => {
|
|
2274
2484
|
stdin.write('\x12');
|
|
@@ -2293,7 +2503,7 @@ describe('InputPrompt', () => {
|
|
|
2293
2503
|
props.buffer.text = 'line 1\nline 2\nline 3';
|
|
2294
2504
|
props.buffer.cursor = [1, 2];
|
|
2295
2505
|
props.buffer.lines = ['line 1', 'line 2', 'line 3'];
|
|
2296
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2506
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2297
2507
|
await act(async () => {
|
|
2298
2508
|
stdin.write('\x05'); // Ctrl+E
|
|
2299
2509
|
});
|
|
@@ -2307,7 +2517,7 @@ describe('InputPrompt', () => {
|
|
|
2307
2517
|
props.buffer.text = 'single line text';
|
|
2308
2518
|
props.buffer.cursor = [0, 5];
|
|
2309
2519
|
props.buffer.lines = ['single line text'];
|
|
2310
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2520
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2311
2521
|
await act(async () => {
|
|
2312
2522
|
stdin.write('\x05'); // Ctrl+E
|
|
2313
2523
|
});
|
|
@@ -2332,7 +2542,7 @@ describe('InputPrompt', () => {
|
|
|
2332
2542
|
showSuggestions: !!isActive,
|
|
2333
2543
|
activeSuggestionIndex: isActive ? 0 : -1,
|
|
2334
2544
|
}));
|
|
2335
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2545
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2336
2546
|
await act(async () => {
|
|
2337
2547
|
stdin.write('\x12'); // Ctrl+R
|
|
2338
2548
|
});
|
|
@@ -2355,7 +2565,7 @@ describe('InputPrompt', () => {
|
|
|
2355
2565
|
visibleStartIndex: 0,
|
|
2356
2566
|
isLoadingSuggestions: false,
|
|
2357
2567
|
});
|
|
2358
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2568
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2359
2569
|
await act(async () => {
|
|
2360
2570
|
stdin.write('\x12');
|
|
2361
2571
|
});
|
|
@@ -2391,7 +2601,7 @@ describe('InputPrompt', () => {
|
|
|
2391
2601
|
visibleStartIndex: 0,
|
|
2392
2602
|
isLoadingSuggestions: false,
|
|
2393
2603
|
});
|
|
2394
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2604
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2395
2605
|
await act(async () => {
|
|
2396
2606
|
stdin.write('\x12');
|
|
2397
2607
|
});
|
|
@@ -2421,7 +2631,7 @@ describe('InputPrompt', () => {
|
|
|
2421
2631
|
visibleStartIndex: 0,
|
|
2422
2632
|
isLoadingSuggestions: false,
|
|
2423
2633
|
});
|
|
2424
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2634
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2425
2635
|
await act(async () => {
|
|
2426
2636
|
stdin.write('\x12');
|
|
2427
2637
|
});
|
|
@@ -2437,7 +2647,7 @@ describe('InputPrompt', () => {
|
|
|
2437
2647
|
it('ensures Ctrl+R search results are prioritized newest-to-oldest by reversing userMessages', async () => {
|
|
2438
2648
|
props.shellModeActive = false;
|
|
2439
2649
|
props.userMessages = ['oldest', 'middle', 'newest'];
|
|
2440
|
-
await renderWithProviders(_jsx(
|
|
2650
|
+
await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2441
2651
|
const calls = vi.mocked(useReverseSearchCompletion).mock.calls;
|
|
2442
2652
|
const commandSearchCall = calls.find((call) => call[1] === props.userMessages ||
|
|
2443
2653
|
(Array.isArray(call[1]) && call[1][0] === 'newest'));
|
|
@@ -2484,7 +2694,7 @@ describe('InputPrompt', () => {
|
|
|
2484
2694
|
markSelected: vi.fn(),
|
|
2485
2695
|
},
|
|
2486
2696
|
});
|
|
2487
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2697
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
2488
2698
|
uiActions,
|
|
2489
2699
|
uiState: {},
|
|
2490
2700
|
});
|
|
@@ -2522,7 +2732,7 @@ describe('InputPrompt', () => {
|
|
|
2522
2732
|
markSelected: vi.fn(),
|
|
2523
2733
|
},
|
|
2524
2734
|
});
|
|
2525
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2735
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
2526
2736
|
uiActions,
|
|
2527
2737
|
});
|
|
2528
2738
|
await act(async () => {
|
|
@@ -2546,7 +2756,7 @@ describe('InputPrompt', () => {
|
|
|
2546
2756
|
markSelected: vi.fn(),
|
|
2547
2757
|
},
|
|
2548
2758
|
});
|
|
2549
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2759
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
2550
2760
|
uiActions,
|
|
2551
2761
|
uiState: { activePtyId: 1, cleanUiDetailsVisible: false },
|
|
2552
2762
|
});
|
|
@@ -2572,7 +2782,7 @@ describe('InputPrompt', () => {
|
|
|
2572
2782
|
markSelected: vi.fn(),
|
|
2573
2783
|
},
|
|
2574
2784
|
});
|
|
2575
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
2785
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
2576
2786
|
uiActions,
|
|
2577
2787
|
uiState: {},
|
|
2578
2788
|
});
|
|
@@ -2619,14 +2829,16 @@ describe('InputPrompt', () => {
|
|
|
2619
2829
|
])('should move cursor on mouse click - $name', async ({ relX, relY, mouseCol, mouseRow }) => {
|
|
2620
2830
|
props.buffer.text = 'hello world\nsecond line';
|
|
2621
2831
|
props.buffer.lines = ['hello world', 'second line'];
|
|
2832
|
+
props.buffer.allVisualLines = ['hello world', 'second line'];
|
|
2622
2833
|
props.buffer.viewportVisualLines = ['hello world', 'second line'];
|
|
2834
|
+
props.buffer.viewportHeight = 10;
|
|
2623
2835
|
props.buffer.visualToLogicalMap = [
|
|
2624
2836
|
[0, 0],
|
|
2625
2837
|
[1, 0],
|
|
2626
2838
|
];
|
|
2627
2839
|
props.buffer.visualCursor = [0, 11];
|
|
2628
2840
|
props.buffer.visualScrollRow = 0;
|
|
2629
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2841
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { mouseEventsEnabled: true, uiActions });
|
|
2630
2842
|
// Wait for initial render
|
|
2631
2843
|
await waitFor(() => {
|
|
2632
2844
|
expect(stdout.lastFrame()).toContain('hello world');
|
|
@@ -2642,12 +2854,9 @@ describe('InputPrompt', () => {
|
|
|
2642
2854
|
unmount();
|
|
2643
2855
|
});
|
|
2644
2856
|
it('should unfocus embedded shell on click', async () => {
|
|
2645
|
-
props.buffer.
|
|
2646
|
-
props.buffer.lines = ['hello'];
|
|
2647
|
-
props.buffer.viewportVisualLines = ['hello'];
|
|
2648
|
-
props.buffer.visualToLogicalMap = [[0, 0]];
|
|
2857
|
+
props.buffer.setText('hello');
|
|
2649
2858
|
props.isEmbeddedShellFocused = true;
|
|
2650
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
2859
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { mouseEventsEnabled: true, uiActions });
|
|
2651
2860
|
await waitFor(() => {
|
|
2652
2861
|
expect(stdout.lastFrame()).toContain('hello');
|
|
2653
2862
|
});
|
|
@@ -2674,6 +2883,7 @@ describe('InputPrompt', () => {
|
|
|
2674
2883
|
lines: currentLines,
|
|
2675
2884
|
viewportVisualLines: currentLines,
|
|
2676
2885
|
allVisualLines: currentLines,
|
|
2886
|
+
viewportHeight: 10,
|
|
2677
2887
|
pastedContent: { [id]: largeText },
|
|
2678
2888
|
transformationsByLine: isExpanded
|
|
2679
2889
|
? currentLines.map(() => [])
|
|
@@ -2703,7 +2913,7 @@ describe('InputPrompt', () => {
|
|
|
2703
2913
|
.fn()
|
|
2704
2914
|
.mockReturnValue(isExpanded ? id : null),
|
|
2705
2915
|
};
|
|
2706
|
-
return _jsx(
|
|
2916
|
+
return _jsx(TestInputPrompt, { ...baseProps, buffer: buffer });
|
|
2707
2917
|
};
|
|
2708
2918
|
const { stdout, unmount, simulateClick } = await renderWithProviders(_jsx(TestWrapper, {}), {
|
|
2709
2919
|
mouseEventsEnabled: true,
|
|
@@ -2745,6 +2955,7 @@ describe('InputPrompt', () => {
|
|
|
2745
2955
|
lines: currentLines,
|
|
2746
2956
|
viewportVisualLines: currentLines,
|
|
2747
2957
|
allVisualLines: currentLines,
|
|
2958
|
+
viewportHeight: 10,
|
|
2748
2959
|
pastedContent: { [id]: largeText },
|
|
2749
2960
|
transformationsByLine: isExpanded
|
|
2750
2961
|
? currentLines.map(() => [])
|
|
@@ -2774,7 +2985,7 @@ describe('InputPrompt', () => {
|
|
|
2774
2985
|
.fn()
|
|
2775
2986
|
.mockImplementation((row) => isExpanded && row >= 0 && row < 10 ? id : null),
|
|
2776
2987
|
};
|
|
2777
|
-
return _jsx(
|
|
2988
|
+
return _jsx(TestInputPrompt, { ...baseProps, buffer: buffer });
|
|
2778
2989
|
};
|
|
2779
2990
|
const { stdout, unmount, simulateClick } = await renderWithProviders(_jsx(TestWrapper, {}), {
|
|
2780
2991
|
mouseEventsEnabled: true,
|
|
@@ -2800,11 +3011,13 @@ describe('InputPrompt', () => {
|
|
|
2800
3011
|
props.config.getUseBackgroundColor = () => false;
|
|
2801
3012
|
props.buffer.text = 'hello world';
|
|
2802
3013
|
props.buffer.lines = ['hello world'];
|
|
3014
|
+
props.buffer.allVisualLines = ['hello world'];
|
|
2803
3015
|
props.buffer.viewportVisualLines = ['hello world'];
|
|
3016
|
+
props.buffer.viewportHeight = 10;
|
|
2804
3017
|
props.buffer.visualToLogicalMap = [[0, 0]];
|
|
2805
3018
|
props.buffer.visualCursor = [0, 11];
|
|
2806
3019
|
props.buffer.visualScrollRow = 0;
|
|
2807
|
-
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(
|
|
3020
|
+
const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { mouseEventsEnabled: true, uiActions });
|
|
2808
3021
|
// Wait for initial render
|
|
2809
3022
|
await waitFor(() => {
|
|
2810
3023
|
expect(stdout.lastFrame()).toContain('hello world');
|
|
@@ -2825,7 +3038,7 @@ describe('InputPrompt', () => {
|
|
|
2825
3038
|
mockPopAllMessages.mockReturnValue('Message 1\n\nMessage 2\n\nMessage 3');
|
|
2826
3039
|
props.popAllMessages = mockPopAllMessages;
|
|
2827
3040
|
props.buffer.text = '';
|
|
2828
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3041
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2829
3042
|
await act(async () => {
|
|
2830
3043
|
stdin.write('\u001B[A');
|
|
2831
3044
|
});
|
|
@@ -2837,7 +3050,7 @@ describe('InputPrompt', () => {
|
|
|
2837
3050
|
const mockPopAllMessages = vi.fn();
|
|
2838
3051
|
props.popAllMessages = mockPopAllMessages;
|
|
2839
3052
|
props.buffer.text = 'some text';
|
|
2840
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3053
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2841
3054
|
await act(async () => {
|
|
2842
3055
|
stdin.write('\u001B[A');
|
|
2843
3056
|
});
|
|
@@ -2850,7 +3063,7 @@ describe('InputPrompt', () => {
|
|
|
2850
3063
|
mockPopAllMessages.mockReturnValue(undefined);
|
|
2851
3064
|
props.popAllMessages = mockPopAllMessages;
|
|
2852
3065
|
props.buffer.text = '';
|
|
2853
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3066
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2854
3067
|
await act(async () => {
|
|
2855
3068
|
stdin.write('\u001B[A');
|
|
2856
3069
|
});
|
|
@@ -2866,7 +3079,7 @@ describe('InputPrompt', () => {
|
|
|
2866
3079
|
props.buffer.allVisualLines = [''];
|
|
2867
3080
|
props.buffer.visualCursor = [0, 0];
|
|
2868
3081
|
props.buffer.visualScrollRow = 0;
|
|
2869
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3082
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2870
3083
|
await act(async () => {
|
|
2871
3084
|
stdin.write('\u001B[A');
|
|
2872
3085
|
});
|
|
@@ -2878,7 +3091,7 @@ describe('InputPrompt', () => {
|
|
|
2878
3091
|
mockPopAllMessages.mockReturnValue('Single message');
|
|
2879
3092
|
props.popAllMessages = mockPopAllMessages;
|
|
2880
3093
|
props.buffer.text = '';
|
|
2881
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3094
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2882
3095
|
await act(async () => {
|
|
2883
3096
|
stdin.write('\u001B[A');
|
|
2884
3097
|
});
|
|
@@ -2890,7 +3103,7 @@ describe('InputPrompt', () => {
|
|
|
2890
3103
|
const mockPopAllMessages = vi.fn();
|
|
2891
3104
|
props.popAllMessages = mockPopAllMessages;
|
|
2892
3105
|
props.buffer.text = ' '; // Whitespace only
|
|
2893
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3106
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2894
3107
|
await act(async () => {
|
|
2895
3108
|
stdin.write('\u001B[A');
|
|
2896
3109
|
});
|
|
@@ -2900,7 +3113,7 @@ describe('InputPrompt', () => {
|
|
|
2900
3113
|
it('should not call popAllMessages if it is not provided', async () => {
|
|
2901
3114
|
props.popAllMessages = undefined;
|
|
2902
3115
|
props.buffer.text = '';
|
|
2903
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3116
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2904
3117
|
await act(async () => {
|
|
2905
3118
|
stdin.write('\u001B[A');
|
|
2906
3119
|
});
|
|
@@ -2912,7 +3125,7 @@ describe('InputPrompt', () => {
|
|
|
2912
3125
|
mockPopAllMessages.mockReturnValue(undefined);
|
|
2913
3126
|
props.popAllMessages = mockPopAllMessages;
|
|
2914
3127
|
props.buffer.text = '';
|
|
2915
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3128
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2916
3129
|
await act(async () => {
|
|
2917
3130
|
stdin.write('\u001B[A');
|
|
2918
3131
|
});
|
|
@@ -2925,21 +3138,21 @@ describe('InputPrompt', () => {
|
|
|
2925
3138
|
describe('snapshots', () => {
|
|
2926
3139
|
it('should render correctly in shell mode', async () => {
|
|
2927
3140
|
props.shellModeActive = true;
|
|
2928
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3141
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2929
3142
|
await waitFor(() => expect(stdout.lastFrame()).toContain('!'));
|
|
2930
3143
|
expect(stdout.lastFrame()).toMatchSnapshot();
|
|
2931
3144
|
unmount();
|
|
2932
3145
|
});
|
|
2933
3146
|
it('should render correctly when accepting edits', async () => {
|
|
2934
3147
|
props.approvalMode = ApprovalMode.AUTO_EDIT;
|
|
2935
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3148
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2936
3149
|
await waitFor(() => expect(stdout.lastFrame()).toContain('>'));
|
|
2937
3150
|
expect(stdout.lastFrame()).toMatchSnapshot();
|
|
2938
3151
|
unmount();
|
|
2939
3152
|
});
|
|
2940
3153
|
it('should render correctly in yolo mode', async () => {
|
|
2941
3154
|
props.approvalMode = ApprovalMode.YOLO;
|
|
2942
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3155
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2943
3156
|
await waitFor(() => expect(stdout.lastFrame()).toContain('*'));
|
|
2944
3157
|
expect(stdout.lastFrame()).toMatchSnapshot();
|
|
2945
3158
|
unmount();
|
|
@@ -2947,14 +3160,14 @@ describe('InputPrompt', () => {
|
|
|
2947
3160
|
it('should not show inverted cursor when shell is focused', async () => {
|
|
2948
3161
|
props.isEmbeddedShellFocused = true;
|
|
2949
3162
|
props.focus = false;
|
|
2950
|
-
const renderResult = await renderWithProviders(_jsx(
|
|
3163
|
+
const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
2951
3164
|
await renderResult.waitUntilReady();
|
|
2952
3165
|
await expect(renderResult).toMatchSvgSnapshot();
|
|
2953
3166
|
renderResult.unmount();
|
|
2954
3167
|
});
|
|
2955
3168
|
});
|
|
2956
3169
|
it('should still allow input when shell is not focused', async () => {
|
|
2957
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3170
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
2958
3171
|
shellFocus: false,
|
|
2959
3172
|
});
|
|
2960
3173
|
await act(async () => {
|
|
@@ -3001,7 +3214,7 @@ describe('InputPrompt', () => {
|
|
|
3001
3214
|
])('$name', async ({ bufferText, shellMode, shouldSubmit, errorMessage }) => {
|
|
3002
3215
|
props.buffer.text = bufferText;
|
|
3003
3216
|
props.shellModeActive = shellMode;
|
|
3004
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3217
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
3005
3218
|
await act(async () => {
|
|
3006
3219
|
stdin.write('\r');
|
|
3007
3220
|
});
|
|
@@ -3021,13 +3234,10 @@ describe('InputPrompt', () => {
|
|
|
3021
3234
|
describe('IME Cursor Support', () => {
|
|
3022
3235
|
it('should report correct cursor position for simple ASCII text', async () => {
|
|
3023
3236
|
const text = 'hello';
|
|
3024
|
-
mockBuffer.text
|
|
3025
|
-
mockBuffer.lines = [text];
|
|
3026
|
-
mockBuffer.viewportVisualLines = [text];
|
|
3027
|
-
mockBuffer.visualToLogicalMap = [[0, 0]];
|
|
3237
|
+
mockBuffer.setText(text);
|
|
3028
3238
|
mockBuffer.visualCursor = [0, 3]; // Cursor after 'hel'
|
|
3029
3239
|
mockBuffer.visualScrollRow = 0;
|
|
3030
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3240
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
|
|
3031
3241
|
await waitFor(() => {
|
|
3032
3242
|
expect(stdout.lastFrame()).toContain('hello');
|
|
3033
3243
|
});
|
|
@@ -3043,13 +3253,10 @@ describe('InputPrompt', () => {
|
|
|
3043
3253
|
});
|
|
3044
3254
|
it('should report correct cursor position for text with double-width characters', async () => {
|
|
3045
3255
|
const text = '👍hello';
|
|
3046
|
-
mockBuffer.text
|
|
3047
|
-
mockBuffer.lines = [text];
|
|
3048
|
-
mockBuffer.viewportVisualLines = [text];
|
|
3049
|
-
mockBuffer.visualToLogicalMap = [[0, 0]];
|
|
3256
|
+
mockBuffer.setText(text);
|
|
3050
3257
|
mockBuffer.visualCursor = [0, 2]; // Cursor after '👍h' (Note: '👍' is one code point but width 2)
|
|
3051
3258
|
mockBuffer.visualScrollRow = 0;
|
|
3052
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3259
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
|
|
3053
3260
|
await waitFor(() => {
|
|
3054
3261
|
expect(stdout.lastFrame()).toContain('👍hello');
|
|
3055
3262
|
});
|
|
@@ -3064,13 +3271,10 @@ describe('InputPrompt', () => {
|
|
|
3064
3271
|
});
|
|
3065
3272
|
it('should report correct cursor position for a line full of "😀" emojis', async () => {
|
|
3066
3273
|
const text = '😀😀😀';
|
|
3067
|
-
mockBuffer.text
|
|
3068
|
-
mockBuffer.lines = [text];
|
|
3069
|
-
mockBuffer.viewportVisualLines = [text];
|
|
3070
|
-
mockBuffer.visualToLogicalMap = [[0, 0]];
|
|
3274
|
+
mockBuffer.setText(text);
|
|
3071
3275
|
mockBuffer.visualCursor = [0, 2]; // Cursor after 2 emojis (each 1 code point, width 2)
|
|
3072
3276
|
mockBuffer.visualScrollRow = 0;
|
|
3073
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3277
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
|
|
3074
3278
|
await waitFor(() => {
|
|
3075
3279
|
expect(stdout.lastFrame()).toContain('😀😀😀');
|
|
3076
3280
|
});
|
|
@@ -3087,7 +3291,9 @@ describe('InputPrompt', () => {
|
|
|
3087
3291
|
const lines = ['😀😀', 'hello 😀', 'world'];
|
|
3088
3292
|
mockBuffer.text = lines.join('\n');
|
|
3089
3293
|
mockBuffer.lines = lines;
|
|
3294
|
+
mockBuffer.allVisualLines = lines;
|
|
3090
3295
|
mockBuffer.viewportVisualLines = lines;
|
|
3296
|
+
mockBuffer.viewportHeight = 10;
|
|
3091
3297
|
mockBuffer.visualToLogicalMap = [
|
|
3092
3298
|
[0, 0],
|
|
3093
3299
|
[1, 0],
|
|
@@ -3095,7 +3301,7 @@ describe('InputPrompt', () => {
|
|
|
3095
3301
|
];
|
|
3096
3302
|
mockBuffer.visualCursor = [1, 7]; // Second line, after 'hello 😀' (6 chars + 1 emoji = 7 code points)
|
|
3097
3303
|
mockBuffer.visualScrollRow = 0;
|
|
3098
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3304
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
|
|
3099
3305
|
await waitFor(() => {
|
|
3100
3306
|
expect(stdout.lastFrame()).toContain('hello 😀');
|
|
3101
3307
|
});
|
|
@@ -3112,7 +3318,9 @@ describe('InputPrompt', () => {
|
|
|
3112
3318
|
const lines = ['first line', 'second line', 'third line'];
|
|
3113
3319
|
mockBuffer.text = lines.join('\n');
|
|
3114
3320
|
mockBuffer.lines = lines;
|
|
3321
|
+
mockBuffer.allVisualLines = lines;
|
|
3115
3322
|
mockBuffer.viewportVisualLines = lines;
|
|
3323
|
+
mockBuffer.viewportHeight = 10;
|
|
3116
3324
|
mockBuffer.visualToLogicalMap = [
|
|
3117
3325
|
[0, 0],
|
|
3118
3326
|
[1, 0],
|
|
@@ -3120,7 +3328,7 @@ describe('InputPrompt', () => {
|
|
|
3120
3328
|
];
|
|
3121
3329
|
mockBuffer.visualCursor = [1, 7]; // Cursor on second line, after 'second '
|
|
3122
3330
|
mockBuffer.visualScrollRow = 0;
|
|
3123
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3331
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
|
|
3124
3332
|
await waitFor(() => {
|
|
3125
3333
|
expect(stdout.lastFrame()).toContain('second line');
|
|
3126
3334
|
});
|
|
@@ -3139,11 +3347,12 @@ describe('InputPrompt', () => {
|
|
|
3139
3347
|
it('should report cursor position 0 when input is empty and placeholder is shown', async () => {
|
|
3140
3348
|
mockBuffer.text = '';
|
|
3141
3349
|
mockBuffer.lines = [''];
|
|
3350
|
+
mockBuffer.allVisualLines = [''];
|
|
3142
3351
|
mockBuffer.viewportVisualLines = [''];
|
|
3143
3352
|
mockBuffer.visualToLogicalMap = [[0, 0]];
|
|
3144
3353
|
mockBuffer.visualCursor = [0, 0];
|
|
3145
3354
|
mockBuffer.visualScrollRow = 0;
|
|
3146
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3355
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, placeholder: "Type here" }), { uiActions });
|
|
3147
3356
|
await waitFor(() => {
|
|
3148
3357
|
expect(stdout.lastFrame()).toContain('Type here');
|
|
3149
3358
|
});
|
|
@@ -3162,18 +3371,19 @@ describe('InputPrompt', () => {
|
|
|
3162
3371
|
const applyVisualState = (visualLine, cursorCol) => {
|
|
3163
3372
|
mockBuffer.text = logicalLine;
|
|
3164
3373
|
mockBuffer.lines = [logicalLine];
|
|
3165
|
-
mockBuffer.viewportVisualLines = [visualLine];
|
|
3166
3374
|
mockBuffer.allVisualLines = [visualLine];
|
|
3375
|
+
mockBuffer.viewportVisualLines = [visualLine];
|
|
3167
3376
|
mockBuffer.visualToLogicalMap = [[0, 0]];
|
|
3168
3377
|
mockBuffer.visualToTransformedMap = [0];
|
|
3169
3378
|
mockBuffer.transformationsByLine = [transformations];
|
|
3170
3379
|
mockBuffer.cursor = [0, cursorCol];
|
|
3171
|
-
mockBuffer.visualCursor = [0,
|
|
3380
|
+
mockBuffer.visualCursor = [0, cursorCol];
|
|
3381
|
+
mockBuffer.visualScrollRow = 0;
|
|
3172
3382
|
};
|
|
3173
3383
|
it('should snapshot collapsed image path', async () => {
|
|
3174
3384
|
const { transformedLine } = calculateTransformedLine(logicalLine, 0, [0, transformations[0].logEnd + 5], transformations);
|
|
3175
3385
|
applyVisualState(transformedLine, transformations[0].logEnd + 5);
|
|
3176
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3386
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
3177
3387
|
await waitFor(() => {
|
|
3178
3388
|
expect(stdout.lastFrame()).toContain('[Image');
|
|
3179
3389
|
});
|
|
@@ -3183,7 +3393,7 @@ describe('InputPrompt', () => {
|
|
|
3183
3393
|
it('should snapshot expanded image path when cursor is on it', async () => {
|
|
3184
3394
|
const { transformedLine } = calculateTransformedLine(logicalLine, 0, [0, transformations[0].logStart + 1], transformations);
|
|
3185
3395
|
applyVisualState(transformedLine, transformations[0].logStart + 1);
|
|
3186
|
-
const { stdout, unmount } = await renderWithProviders(_jsx(
|
|
3396
|
+
const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
|
|
3187
3397
|
await waitFor(() => {
|
|
3188
3398
|
expect(stdout.lastFrame()).toContain('@/path/to/screenshots');
|
|
3189
3399
|
});
|
|
@@ -3219,7 +3429,7 @@ describe('InputPrompt', () => {
|
|
|
3219
3429
|
getExpandedPasteAtLine: vi.fn().mockReturnValue(null),
|
|
3220
3430
|
togglePasteExpansion: toggleFn,
|
|
3221
3431
|
};
|
|
3222
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3432
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, buffer: buffer }), { uiActions });
|
|
3223
3433
|
await act(async () => {
|
|
3224
3434
|
stdin.write(CTRL_O);
|
|
3225
3435
|
});
|
|
@@ -3262,7 +3472,7 @@ describe('InputPrompt', () => {
|
|
|
3262
3472
|
checking: false,
|
|
3263
3473
|
});
|
|
3264
3474
|
}
|
|
3265
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3475
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, buffer: method === 'terminal-paste' ? buffer : props.buffer }));
|
|
3266
3476
|
await act(async () => {
|
|
3267
3477
|
if (method === 'ctrl-v') {
|
|
3268
3478
|
stdin.write('\x16'); // Ctrl+V
|
|
@@ -3424,7 +3634,7 @@ describe('InputPrompt', () => {
|
|
|
3424
3634
|
{ name: 'Up arrow', key: '\u001B[A', position: 'start' },
|
|
3425
3635
|
{ name: 'Ctrl+P', key: '\u0010', position: 'start' },
|
|
3426
3636
|
])('should move cursor to $position on $name (older history)', async ({ key, position }) => {
|
|
3427
|
-
const { stdin } = await renderWithProviders(_jsx(
|
|
3637
|
+
const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
3428
3638
|
uiActions,
|
|
3429
3639
|
});
|
|
3430
3640
|
await act(async () => {
|
|
@@ -3438,7 +3648,7 @@ describe('InputPrompt', () => {
|
|
|
3438
3648
|
{ name: 'Down arrow', key: '\u001B[B', position: 'end' },
|
|
3439
3649
|
{ name: 'Ctrl+N', key: '\u000E', position: 'end' },
|
|
3440
3650
|
])('should move cursor to $position on $name (newer history)', async ({ key, position }) => {
|
|
3441
|
-
const { stdin } = await renderWithProviders(_jsx(
|
|
3651
|
+
const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
3442
3652
|
uiActions,
|
|
3443
3653
|
});
|
|
3444
3654
|
// First go up
|
|
@@ -3458,7 +3668,7 @@ describe('InputPrompt', () => {
|
|
|
3458
3668
|
});
|
|
3459
3669
|
});
|
|
3460
3670
|
it('should suppress completion after history navigation', async () => {
|
|
3461
|
-
const { stdin } = await renderWithProviders(_jsx(
|
|
3671
|
+
const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
3462
3672
|
uiActions,
|
|
3463
3673
|
});
|
|
3464
3674
|
await act(async () => {
|
|
@@ -3486,7 +3696,7 @@ describe('InputPrompt', () => {
|
|
|
3486
3696
|
? [{ value: 'suggestion', label: 'suggestion' }]
|
|
3487
3697
|
: [],
|
|
3488
3698
|
}));
|
|
3489
|
-
const { stdout, stdin, unmount } = await renderWithProviders(_jsx(
|
|
3699
|
+
const { stdout, stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
|
|
3490
3700
|
// 2. Verify suggestions ARE showing initially because active is true by default
|
|
3491
3701
|
await waitFor(() => {
|
|
3492
3702
|
expect(stdout.lastFrame()).toContain('suggestion');
|
|
@@ -3503,7 +3713,7 @@ describe('InputPrompt', () => {
|
|
|
3503
3713
|
unmount();
|
|
3504
3714
|
});
|
|
3505
3715
|
it('should continue to suppress completion after manual cursor movement', async () => {
|
|
3506
|
-
const { stdin } = await renderWithProviders(_jsx(
|
|
3716
|
+
const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
3507
3717
|
uiActions,
|
|
3508
3718
|
});
|
|
3509
3719
|
// Navigate history (suppresses)
|
|
@@ -3541,7 +3751,7 @@ describe('InputPrompt', () => {
|
|
|
3541
3751
|
});
|
|
3542
3752
|
});
|
|
3543
3753
|
it('should re-enable completion after typing', async () => {
|
|
3544
|
-
const { stdin } = await renderWithProviders(_jsx(
|
|
3754
|
+
const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
3545
3755
|
uiActions,
|
|
3546
3756
|
});
|
|
3547
3757
|
// Navigate history (suppresses)
|
|
@@ -3567,7 +3777,7 @@ describe('InputPrompt', () => {
|
|
|
3567
3777
|
const settings = createMockSettings({
|
|
3568
3778
|
ui: { showShortcutsHint: false },
|
|
3569
3779
|
});
|
|
3570
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3780
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
3571
3781
|
settings,
|
|
3572
3782
|
uiActions: { setShortcutsHelpVisible },
|
|
3573
3783
|
});
|
|
@@ -3606,8 +3816,8 @@ describe('InputPrompt', () => {
|
|
|
3606
3816
|
input: '\x12',
|
|
3607
3817
|
},
|
|
3608
3818
|
{
|
|
3609
|
-
name: 'Ctrl+
|
|
3610
|
-
input: '\
|
|
3819
|
+
name: 'Ctrl+G hotkey is pressed',
|
|
3820
|
+
input: '\x07',
|
|
3611
3821
|
},
|
|
3612
3822
|
{
|
|
3613
3823
|
name: 'F12 hotkey is pressed',
|
|
@@ -3616,7 +3826,7 @@ describe('InputPrompt', () => {
|
|
|
3616
3826
|
])('should close shortcuts help when a $name', async ({ input, setupMocks, mouseEventsEnabled }) => {
|
|
3617
3827
|
setupMocks?.();
|
|
3618
3828
|
const setShortcutsHelpVisible = vi.fn();
|
|
3619
|
-
const { stdin, unmount } = await renderWithProviders(_jsx(
|
|
3829
|
+
const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
|
|
3620
3830
|
uiState: { shortcutsHelpVisible: true },
|
|
3621
3831
|
uiActions: { setShortcutsHelpVisible },
|
|
3622
3832
|
mouseEventsEnabled,
|