Skip to content

Commit fb369bb

Browse files
test(task): guard immediate clean state on start
Verify stale webview messages are cleared and posted through the immediate state path before the first task message. This keeps task startup outside the throttled update path. Signed-off-by: JunyongParkDev <jun94.park@samsung.com>
1 parent 0b02f7d commit fb369bb

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

src/core/task/__tests__/Task.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import type { ApiMessage } from "../../task-persistence"
2727

2828
type TaskTestAccess = {
2929
getSystemPrompt: () => Promise<string>
30+
getEnabledMcpToolsCount: () => Promise<{ enabledToolCount: number; enabledServerCount: number }>
31+
initiateTaskLoop: (userContent: Anthropic.Messages.ContentBlockParam[]) => Promise<void>
3032
startTask: (task?: string, images?: string[]) => Promise<void>
3133
resumeTaskFromHistory: () => Promise<void>
3234
presentAssistantMessageSafe: () => void
@@ -2849,6 +2851,50 @@ describe("Cline", () => {
28492851
})
28502852
})
28512853

2854+
describe("startTask", () => {
2855+
it("posts a clean state immediately before adding the first task message", async () => {
2856+
const task = new Task({
2857+
provider: mockProvider,
2858+
apiConfiguration: mockApiConfig,
2859+
task: "new task",
2860+
startTask: false,
2861+
})
2862+
const taskAccess = getTaskTestAccess(task)
2863+
2864+
task.clineMessages = [{ ts: 1, type: "say", say: "text", text: "stale message" }]
2865+
2866+
let resolvePostState: (() => void) | undefined
2867+
const pendingPostState = new Promise<void>((resolve) => {
2868+
resolvePostState = resolve
2869+
})
2870+
const postStateSpy = vi
2871+
.mocked(mockProvider.postStateToWebviewWithoutTaskHistory)
2872+
.mockImplementationOnce(async () => {
2873+
expect(task.clineMessages).toEqual([])
2874+
await pendingPostState
2875+
})
2876+
const saySpy = vi.spyOn(task, "say").mockResolvedValue(undefined)
2877+
vi.spyOn(taskAccess, "getEnabledMcpToolsCount").mockResolvedValue({
2878+
enabledToolCount: 0,
2879+
enabledServerCount: 0,
2880+
})
2881+
const initiateTaskLoopSpy = vi.spyOn(taskAccess, "initiateTaskLoop").mockResolvedValue(undefined)
2882+
2883+
const startPromise = taskAccess.startTask("new task")
2884+
2885+
expect(postStateSpy).toHaveBeenCalledTimes(1)
2886+
expect(mockProvider.postStateToWebviewThrottled).not.toHaveBeenCalled()
2887+
expect(saySpy).not.toHaveBeenCalled()
2888+
2889+
resolvePostState?.()
2890+
await startPromise
2891+
2892+
expect(saySpy).toHaveBeenCalledOnce()
2893+
expect(saySpy).toHaveBeenCalledWith("text", "new task", undefined)
2894+
expect(initiateTaskLoopSpy).toHaveBeenCalledOnce()
2895+
})
2896+
})
2897+
28522898
describe("start()", () => {
28532899
it("should be a no-op if the task was already started in the constructor", () => {
28542900
const task = new Task({

0 commit comments

Comments
 (0)