diff --git a/webview-ui/src/components/chat/TaskActions.tsx b/webview-ui/src/components/chat/TaskActions.tsx index 2eebc6ccb3..18325af8fb 100644 --- a/webview-ui/src/components/chat/TaskActions.tsx +++ b/webview-ui/src/components/chat/TaskActions.tsx @@ -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(null) const { t } = useTranslation() @@ -29,12 +28,6 @@ export const TaskActions = ({ item, buttonsDisabled, handleCondenseContext }: Ta /> {!!item?.size && item.size > 0 && ( <> - handleCondenseContext(item.id)} - />
{/* Collapsed state: Track context and cost if we have any */} {!isTaskExpanded && contextWindow > 0 && ( -
+
+ currentTaskItem && handleCondenseContext(currentTaskItem.id)} + className="shrink-0 min-h-[20px] min-w-[20px] p-[2px]" + /> {!!totalCost && ${totalCost.toFixed(2)}}
)} @@ -169,13 +177,7 @@ const TaskHeader = ({ )}
- {!totalCost && ( - - )} + {!totalCost && }
{doesModelSupportPromptCache && @@ -204,11 +206,7 @@ const TaskHeader = ({ {t("chat:task.apiCost")} ${totalCost?.toFixed(2)} - + )} diff --git a/webview-ui/src/components/chat/__tests__/TaskHeader.test.tsx b/webview-ui/src/components/chat/__tests__/TaskHeader.test.tsx index 12f43b8bea..9d0de80191 100644 --- a/webview-ui/src/components/chat/__tests__/TaskHeader.test.tsx +++ b/webview-ui/src/components/chat/__tests__/TaskHeader.test.tsx @@ -1,13 +1,25 @@ // 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 initReactI18next to prevent initialization errors in tests + initReactI18next: { + type: "3rdParty", + init: jest.fn(), + }, +})) + // Mock the vscode API jest.mock("@/utils/vscode", () => ({ vscode: { @@ -28,7 +40,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" }, }), })) @@ -79,4 +91,25 @@ 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", () => { + const handleCondenseContext = jest.fn() + renderTaskHeader({ buttonsDisabled: true, handleCondenseContext }) + const condenseButton = screen.getByTitle("chat:task.condenseContext") + fireEvent.click(condenseButton) + expect(handleCondenseContext).not.toHaveBeenCalled() + }) })