Skip to content

Commit f63c1ac

Browse files
committed
test: adding a unit test in Task.test.ts to test whether maxContextWindow overtakes the model's Gemini context window value setting
1 parent 93ecb9e commit f63c1ac

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

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

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ClineProvider } from "../../webview/ClineProvider"
1414
import { ApiStreamChunk } from "../../../api/transform/stream"
1515
import { ContextProxy } from "../../config/ContextProxy"
1616
import { processUserContentMentions } from "../../mentions/processUserContentMentions"
17+
import * as slidingWindow from "../../sliding-window"
1718

1819
jest.mock("execa", () => ({
1920
execa: jest.fn(),
@@ -533,6 +534,82 @@ describe("Cline", () => {
533534
})
534535
})
535536

537+
it("should use maxContextWindow when provider is gemini and maxContextWindow is set", async () => {
538+
// Arrange: set apiProvider to gemini and maxContextWindow
539+
const geminiConfig = {
540+
...mockApiConfig,
541+
apiProvider: "gemini" as const,
542+
maxContextWindow: 42,
543+
}
544+
const created = Task.create({
545+
provider: mockProvider,
546+
apiConfiguration: geminiConfig,
547+
task: "test gemini context window",
548+
}) as unknown as [any, Promise<void>]
549+
const cline = created[0] as any
550+
const task = created[1] as Promise<void>
551+
552+
// Stub model info to have a different default contextWindow
553+
;(cline.api as any).getModel = jest.fn().mockReturnValue({
554+
id: "gemini-model",
555+
info: {
556+
contextWindow: 100,
557+
supportsReasoningBudget: true,
558+
maxTokens: 1000,
559+
supportsComputerUse: false,
560+
supportsPromptCache: false,
561+
inputPrice: 0,
562+
outputPrice: 0,
563+
},
564+
})
565+
566+
// Stub required methods to let attemptApiRequest proceed
567+
;(cline as any).getSystemPrompt = jest.fn().mockResolvedValue("")
568+
;(cline as any).getTokenUsage = jest.fn().mockReturnValue({
569+
contextTokens: 1,
570+
totalTokensIn: 0,
571+
totalTokensOut: 0,
572+
totalCost: 0,
573+
})
574+
575+
// Stub createMessage to avoid real API calls
576+
jest.spyOn(cline.api as any, "createMessage").mockReturnValue((async function* () {})())
577+
578+
// Spy on truncateConversationIfNeeded to capture its options
579+
const twSpy = jest.spyOn(slidingWindow, "truncateConversationIfNeeded").mockResolvedValue({
580+
messages: [],
581+
summary: "",
582+
cost: 0,
583+
prevContextTokens: 0,
584+
newContextTokens: 0,
585+
error: undefined,
586+
})
587+
588+
// Force abort immediately so the stream loop exits
589+
Object.defineProperty(cline, "abort", {
590+
get: () => true,
591+
set: () => {},
592+
configurable: true,
593+
})
594+
595+
// Act: run through the generator
596+
try {
597+
for await (const _ of cline.attemptApiRequest()) {
598+
}
599+
} catch {
600+
/* ignore */
601+
}
602+
603+
// Assert: the contextWindow passed to truncateConversationIfNeeded is the maxContextWindow
604+
expect(twSpy).toHaveBeenCalled()
605+
const optionsPassed = twSpy.mock.calls[0][0]
606+
expect(optionsPassed.contextWindow).toBe(42)
607+
608+
// Cleanup
609+
await cline.abortTask(true)
610+
await task.catch(() => {})
611+
})
612+
536613
it.skip("should handle API retry with countdown", async () => {
537614
const [cline, task] = Task.create({
538615
provider: mockProvider,

0 commit comments

Comments
 (0)