Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions webview-ui/src/components/chat/TaskActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ import { IconButton } from "./IconButton"
interface TaskActionsProps {
item?: HistoryItem
buttonsDisabled: boolean
handleCondenseContext: (taskId: string) => void
}

export const TaskActions = ({ item, buttonsDisabled, handleCondenseContext }: TaskActionsProps) => {
export const TaskActions = ({ item, buttonsDisabled }: TaskActionsProps) => {
const [deleteTaskId, setDeleteTaskId] = useState<string | null>(null)
const { t } = useTranslation()

Expand All @@ -29,12 +28,6 @@ export const TaskActions = ({ item, buttonsDisabled, handleCondenseContext }: Ta
/>
{!!item?.size && item.size > 0 && (
<>
<IconButton
iconClass="codicon-fold"
title={t("chat:task.condenseContext")}
disabled={buttonsDisabled}
onClick={() => handleCondenseContext(item.id)}
/>
<div className="flex items-center">
<IconButton
iconClass="codicon-trash"
Expand Down
25 changes: 12 additions & 13 deletions webview-ui/src/components/chat/TaskHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Thumbnails from "../common/Thumbnails"
import { TaskActions } from "./TaskActions"
import { ContextWindowProgress } from "./ContextWindowProgress"
import { Mention } from "./Mention"
import { IconButton } from "./IconButton"

export interface TaskHeaderProps {
task: ClineMessage
Expand Down Expand Up @@ -97,7 +98,7 @@ const TaskHeader = ({
</div>
{/* Collapsed state: Track context and cost if we have any */}
{!isTaskExpanded && contextWindow > 0 && (
<div className={`w-full flex flex-row gap-1 h-auto`}>
<div className={`w-full flex flex-row items-center gap-1 h-auto`}>
<ContextWindowProgress
contextWindow={contextWindow}
contextTokens={contextTokens || 0}
Expand All @@ -107,6 +108,14 @@ const TaskHeader = ({
: undefined
}
/>
<IconButton
iconClass="codicon-fold"
title={t("chat:task.condenseContext")}
disabled={buttonsDisabled}
onClick={() => currentTaskItem && handleCondenseContext(currentTaskItem.id)}
className="shrink-0"
style={{ minHeight: "20px", minWidth: "20px", padding: "2px" }}
/>
{!!totalCost && <VSCodeBadge>${totalCost.toFixed(2)}</VSCodeBadge>}
</div>
)}
Expand Down Expand Up @@ -169,13 +178,7 @@ const TaskHeader = ({
</span>
)}
</div>
{!totalCost && (
<TaskActions
item={currentTaskItem}
buttonsDisabled={buttonsDisabled}
handleCondenseContext={handleCondenseContext}
/>
)}
{!totalCost && <TaskActions item={currentTaskItem} buttonsDisabled={buttonsDisabled} />}
</div>

{doesModelSupportPromptCache &&
Expand Down Expand Up @@ -204,11 +207,7 @@ const TaskHeader = ({
<span className="font-bold">{t("chat:task.apiCost")}</span>
<span>${totalCost?.toFixed(2)}</span>
</div>
<TaskActions
item={currentTaskItem}
buttonsDisabled={buttonsDisabled}
handleCondenseContext={handleCondenseContext}
/>
<TaskActions item={currentTaskItem} buttonsDisabled={buttonsDisabled} />
</div>
)}
</div>
Expand Down
30 changes: 28 additions & 2 deletions webview-ui/src/components/chat/__tests__/TaskHeader.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
// npx jest src/components/chat/__tests__/TaskHeader.test.tsx

import React from "react"
import { render, screen } from "@testing-library/react"
import { render, screen, fireEvent } from "@testing-library/react"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"

import type { ProviderSettings } from "@roo-code/types"

import TaskHeader, { TaskHeaderProps } from "../TaskHeader"

// Mock i18n
jest.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key: string) => key, // Simple mock that returns the key
}),
}))

// Mock the vscode API
jest.mock("@/utils/vscode", () => ({
vscode: {
Expand All @@ -28,7 +35,7 @@ jest.mock("@src/context/ExtensionStateContext", () => ({
apiKey: "test-api-key", // Add relevant fields
apiModelId: "claude-3-opus-20240229", // Add relevant fields
} as ProviderSettings, // Optional: Add type assertion if ProviderSettings is imported
currentTaskItem: null,
currentTaskItem: { id: "test-task-id" }, // Add a mock currentTaskItem for the condense button
}),
}))

Expand Down Expand Up @@ -79,4 +86,23 @@ describe("TaskHeader", () => {
renderTaskHeader({ totalCost: NaN })
expect(screen.queryByText(/\$/)).not.toBeInTheDocument()
})

it("should render the condense context button", () => {
renderTaskHeader()
expect(screen.getByTitle("chat:task.condenseContext")).toBeInTheDocument()
})

it("should call handleCondenseContext when condense context button is clicked", () => {
const handleCondenseContext = jest.fn()
renderTaskHeader({ handleCondenseContext })
const condenseButton = screen.getByTitle("chat:task.condenseContext")
fireEvent.click(condenseButton)
expect(handleCondenseContext).toHaveBeenCalledWith("test-task-id")
})

it("should disable the condense context button when buttonsDisabled is true", () => {
renderTaskHeader({ buttonsDisabled: true })
const condenseButton = screen.getByTitle("chat:task.condenseContext")
expect(condenseButton).toBeDisabled()
})
})
Loading