Adding a terminate task button to quit and restart

This commit is contained in:
John Stearns
2024-11-05 14:40:03 -08:00
parent 8150aa8f1a
commit f73ffd9ea7
4 changed files with 156 additions and 6 deletions

View File

@@ -2,7 +2,7 @@
"name": "roo-cline",
"displayName": "Roo Cline",
"description": "Autonomous coding agent right in your IDE, capable of creating/editing files, running commands, using the browser, and more with your permission every step of the way.",
"version": "1.0.3",
"version": "1.0.4",
"icon": "assets/icons/icon.png",
"galleryBanner": {
"color": "#617A91",

View File

@@ -146,8 +146,8 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
setClineAsk("resume_task")
setEnableButtons(true)
setPrimaryButtonText("Resume Task")
setSecondaryButtonText(undefined)
setDidClickCancel(false) // special case where we reset the cancel button state
setSecondaryButtonText("Terminate")
setDidClickCancel(false)
break
case "resume_completed_task":
setTextAreaDisabled(false)
@@ -316,20 +316,18 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
switch (clineAsk) {
case "api_req_failed":
case "mistake_limit_reached":
case "resume_task":
startNewTask()
break
case "command":
case "tool":
case "browser_action_launch":
// responds to the API with a "This operation failed" and lets it try again
vscode.postMessage({ type: "askResponse", askResponse: "noButtonClicked" })
break
}
setTextAreaDisabled(true)
setClineAsk(undefined)
setEnableButtons(false)
// setPrimaryButtonText(undefined)
// setSecondaryButtonText(undefined)
disableAutoScrollRef.current = false
}, [clineAsk, startNewTask, isStreaming])

View File

@@ -0,0 +1,152 @@
import { render, screen, act } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { ExtensionStateContextType } from '../../../context/ExtensionStateContext'
import ChatView from '../ChatView'
import { vscode } from '../../../utils/vscode'
import * as ExtensionStateContext from '../../../context/ExtensionStateContext'
// Mock vscode
jest.mock('../../../utils/vscode', () => ({
vscode: {
postMessage: jest.fn()
}
}))
// Mock all components that use problematic dependencies
jest.mock('../../common/CodeBlock', () => ({
__esModule: true,
default: () => <div data-testid="mock-code-block" />
}))
jest.mock('../../common/MarkdownBlock', () => ({
__esModule: true,
default: () => <div data-testid="mock-markdown-block" />
}))
jest.mock('../BrowserSessionRow', () => ({
__esModule: true,
default: () => <div data-testid="mock-browser-session-row" />
}))
// Update ChatRow mock to capture props
let chatRowProps = null
jest.mock('../ChatRow', () => ({
__esModule: true,
default: (props: any) => {
chatRowProps = props
return <div data-testid="mock-chat-row" />
}
}))
// Mock Virtuoso component
jest.mock('react-virtuoso', () => ({
Virtuoso: ({ children }: any) => (
<div data-testid="mock-virtuoso">{children}</div>
)
}))
// Mock VS Code components
jest.mock('@vscode/webview-ui-toolkit/react', () => ({
VSCodeButton: ({ children, onClick }: any) => (
<button onClick={onClick}>{children}</button>
),
VSCodeProgressRing: () => <div data-testid="progress-ring" />
}))
describe('ChatView', () => {
const mockShowHistoryView = jest.fn()
const mockHideAnnouncement = jest.fn()
let mockState: ExtensionStateContextType
beforeEach(() => {
jest.clearAllMocks()
mockState = {
clineMessages: [],
apiConfiguration: {
apiProvider: 'anthropic',
apiModelId: 'claude-3-sonnet'
},
version: '1.0.0',
customInstructions: '',
alwaysAllowReadOnly: true,
alwaysAllowWrite: true,
alwaysAllowExecute: true,
openRouterModels: {},
didHydrateState: true,
showWelcome: false,
theme: 'dark',
filePaths: [],
taskHistory: [],
shouldShowAnnouncement: false,
uriScheme: 'vscode',
setAlwaysAllowReadOnly: jest.fn(),
setAlwaysAllowWrite: jest.fn(),
setCustomInstructions: jest.fn(),
setAlwaysAllowExecute: jest.fn(),
setApiConfiguration: jest.fn(),
setShowAnnouncement: jest.fn()
}
// Mock the useExtensionState hook
jest.spyOn(ExtensionStateContext, 'useExtensionState').mockReturnValue(mockState)
})
const renderChatView = () => {
return render(
<ChatView
isHidden={false}
showAnnouncement={false}
hideAnnouncement={mockHideAnnouncement}
showHistoryView={mockShowHistoryView}
/>
)
}
describe('Streaming State', () => {
it('should show cancel button while streaming', () => {
mockState.clineMessages = [
{
type: 'say',
partial: true,
ts: Date.now(),
}
]
renderChatView()
const buttons = screen.queryAllByRole('button')
expect(buttons.length).toBeGreaterThan(0)
})
it('should show terminate button when task is paused', () => {
mockState.clineMessages = [
{
type: 'ask',
ask: 'resume_task',
ts: Date.now(),
}
]
renderChatView()
const buttons = screen.queryAllByRole('button')
expect(buttons.length).toBeGreaterThan(0)
})
it('should show retry button when API error occurs', () => {
mockState.clineMessages = [
{
type: 'say',
say: 'error',
ts: Date.now(),
}
]
renderChatView()
const buttons = screen.queryAllByRole('button')
expect(buttons.length).toBeGreaterThan(0)
})
})
})